Browse Source

Changes:

- v0.14 version bump (not done yet)
- clean up of projbook project files on disk
- fix in path read in @snippet statement
- added references to System.Collections.Immutable to several projects
as it's indirectly loaded and will make docnet fail at runtime if
missing
tags/v0.14
Frans Bouma 8 years ago
parent
commit
71105f3961
30 changed files with 100 additions and 1450 deletions
  1. +2
    -2
      src/DocNet/App.config
  2. +9
    -2
      src/DocNet/Docnet.csproj
  3. +2
    -2
      src/DocNet/Properties/AssemblyInfo.cs
  4. +2
    -2
      src/DocNet/SimpleNavigationElement.cs
  5. +13
    -10
      src/DocNet/Utils.cs
  6. +2
    -1
      src/DocNet/packages.config
  7. +1
    -1
      src/MarkdownDeep/BlockProcessor.cs
  8. +7
    -3
      src/MarkdownDeep/MardownDeep.cs
  9. +5
    -0
      src/MarkdownDeep/MarkdownDeep.csproj
  10. +15
    -0
      src/MarkdownDeep/app.config
  11. +4
    -0
      src/MarkdownDeepTests/MarkdownDeepTests.csproj
  12. +12
    -0
      src/MarkdownDeepTests/app.config
  13. +1
    -0
      src/MarkdownDeepTests/packages.config
  14. +0
    -90
      src/Projbook.Extension.CSharpExtractor/Projbook.Extension.CSharpExtractor.csproj
  15. +0
    -23
      src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpExtractionMode.cs
  16. +0
    -80
      src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpMatchingRule.cs
  17. +0
    -368
      src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSnippetExtractor.cs
  18. +0
    -201
      src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxMatchingNode.cs
  19. +0
    -329
      src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxWalkerMatchingBuilder.cs
  20. +0
    -36
      src/Projbook.Extension.CSharpExtractor/Properties/AssemblyInfo.cs
  21. +0
    -9
      src/Projbook.Extension.CSharpExtractor/packages.config
  22. +0
    -68
      src/Projbook.Extension.XmlExtractor/Projbook.Extension.XmlExtractor.csproj
  23. +0
    -159
      src/Projbook.Extension.XmlExtractor/Projbook/Extension/Xml/XmlSnippetExtractor.cs
  24. +0
    -36
      src/Projbook.Extension.XmlExtractor/Properties/AssemblyInfo.cs
  25. +0
    -5
      src/Projbook.Extension.XmlExtractor/packages.config
  26. +2
    -2
      src/Projbook.Extension/Exception/SnippetExtractionException.cs
  27. +1
    -1
      src/Projbook.Extension/Extractors/CSharp/CSharpMatchingRule.cs
  28. +6
    -4
      src/Projbook.Extension/Projbook.Extension.csproj
  29. +6
    -6
      src/Projbook.Extension/app.config
  30. +10
    -10
      src/Projbook.Extension/packages.config

+ 2
- 2
src/DocNet/App.config View File

@@ -7,11 +7,11 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
<bindingRedirect oldVersion="0.0.0.0-1.4.1.0" newVersion="1.4.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

+ 9
- 2
src/DocNet/Docnet.csproj View File

@@ -33,11 +33,15 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Web" />
@@ -72,6 +76,9 @@
<Name>MarkdownDeep</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.


+ 2
- 2
src/DocNet/Properties/AssemblyInfo.cs View File

@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.13.2.0")]
[assembly: AssemblyFileVersion("0.13.2")]
[assembly: AssemblyVersion("0.14.0.0")]
[assembly: AssemblyFileVersion("0.14.0")]

+ 2
- 2
src/DocNet/SimpleNavigationElement.cs View File

@@ -68,7 +68,7 @@ namespace Docnet
this.MarkdownFromFile = File.ReadAllText(sourceFile, Encoding.UTF8);
// Check if the content contains @@include tag
content = Utils.IncludeProcessor(this.MarkdownFromFile, Utils.MakeAbsolutePath(activeConfig.Source, activeConfig.IncludeFolder));
content = Utils.ConvertMarkdownToHtml(content, Path.GetDirectoryName(destinationFile), activeConfig.Destination, _relativeH2LinksOnPage);
content = Utils.ConvertMarkdownToHtml(content, Path.GetDirectoryName(destinationFile), activeConfig.Destination, sourceFile, _relativeH2LinksOnPage);
}
else
{
@@ -90,7 +90,7 @@ namespace Docnet
defaultMarkdown.AppendFormat("* [{0}]({1}{2}){3}", sibling.Name, relativePathToRoot, HttpUtility.UrlPathEncode(sibling.TargetURL), Environment.NewLine);
}
defaultMarkdown.Append(Environment.NewLine);
content = Utils.ConvertMarkdownToHtml(defaultMarkdown.ToString(), Path.GetDirectoryName(destinationFile), activeConfig.Destination, _relativeH2LinksOnPage);
content = Utils.ConvertMarkdownToHtml(defaultMarkdown.ToString(), Path.GetDirectoryName(destinationFile), activeConfig.Destination, string.Empty, _relativeH2LinksOnPage);
}
else
{


+ 13
- 10
src/DocNet/Utils.cs View File

@@ -39,15 +39,17 @@ namespace Docnet
private static Regex includeRegex = new Regex(@"@@include\((.*)\)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
#endregion

/// <summary>
/// Converts the markdown to HTML.
/// </summary>
/// <param name="toConvert">The markdown string to convert.</param>
/// <param name="documentPath">The document path (without the document filename).</param>
/// <param name="siteRoot">The site root.</param>
/// <param name="createdAnchorCollector">The created anchor collector, for ToC sublinks for H2 headers.</param>
/// <returns></returns>
public static string ConvertMarkdownToHtml(string toConvert, string documentPath, string siteRoot, List<Tuple<string, string>> createdAnchorCollector)
/// <summary>
/// Converts the markdown to HTML.
/// </summary>
/// <param name="toConvert">The markdown string to convert.</param>
/// <param name="destinationDocumentPath">The document path (without the document filename).</param>
/// <param name="siteRoot">The site root.</param>
/// <param name="sourceDocumentFilename">the filename of the source markdown file</param>
/// <param name="createdAnchorCollector">The created anchor collector, for ToC sublinks for H2 headers.</param>
/// <returns></returns>
public static string ConvertMarkdownToHtml(string toConvert, string destinationDocumentPath, string siteRoot, string sourceDocumentFilename,
List<Tuple<string, string>> createdAnchorCollector)
{
var parser = new MarkdownDeep.Markdown
{
@@ -56,8 +58,9 @@ namespace Docnet
AutoHeadingIDs = true,
NewWindowForExternalLinks = true,
DocNetMode = true,
DocumentLocation = documentPath,
DestinationDocumentLocation = destinationDocumentPath,
DocumentRoot = siteRoot,
SourceDocumentFilename = sourceDocumentFilename,
HtmlClassTitledImages = "figure",
};



+ 2
- 1
src/DocNet/packages.config View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net461" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" />
<package id="System.Collections.Immutable" version="1.3.0" targetFramework="net461" />
</packages>

+ 1
- 1
src/MarkdownDeep/BlockProcessor.cs View File

@@ -1533,7 +1533,7 @@ namespace MarkdownDeep
}

// extract the snippet, then build the fenced block to return.
var fullFilename = Path.Combine(Path.GetDirectoryName(m_markdown.DocumentLocation) ?? string.Empty, filename);
var fullFilename = Path.Combine(Path.GetDirectoryName(m_markdown.SourceDocumentFilename) ?? string.Empty, filename);
var snippetText = extractor.Extract(fullFilename, pattern) ?? string.Empty;
b.BlockType = BlockType.codeblock;
b.Data = language;


+ 7
- 3
src/MarkdownDeep/MardownDeep.cs View File

@@ -299,7 +299,7 @@ namespace MarkdownDeep
return false;

// Work out base location
string str = url.StartsWith("/") ? DocumentRoot : DocumentLocation;
string str = url.StartsWith("/") ? DocumentRoot : DestinationDocumentLocation;
if (String.IsNullOrEmpty(str))
return false;

@@ -909,15 +909,19 @@ namespace MarkdownDeep
set;
}

// Local file system location of the current document. Used to locate relative
// Local file system location of the current destination document. Used to locate relative
// path images for image size.
// Typical value: c:\inetpub\www\wwwroot\subfolder
public string DocumentLocation
public string DestinationDocumentLocation
{
get;
set;
}


public string SourceDocumentFilename { get; set; }


// Limit the width of images (0 for no limit)
public int MaxImageWidth
{


+ 5
- 0
src/MarkdownDeep/MarkdownDeep.csproj View File

@@ -44,6 +44,8 @@
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -111,6 +113,9 @@
<Name>Projbook.Extension</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>


+ 15
- 0
src/MarkdownDeep/app.config View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.1.0" newVersion="1.4.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

+ 4
- 0
src/MarkdownDeepTests/MarkdownDeepTests.csproj View File

@@ -51,6 +51,10 @@
<HintPath>..\..\packages\NUnit.2.5.10.11092\lib\pnunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>


+ 12
- 0
src/MarkdownDeepTests/app.config View File

@@ -10,4 +10,16 @@
<add key="ApartmentState" value="STA" />
</TestRunner>
</NUnit>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.1.0" newVersion="1.4.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

+ 1
- 0
src/MarkdownDeepTests/packages.config View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="2.5.10.11092" />
<package id="System.Collections.Immutable" version="1.3.0" targetFramework="net461" />
</packages>

+ 0
- 90
src/Projbook.Extension.CSharpExtractor/Projbook.Extension.CSharpExtractor.csproj View File

@@ -1,90 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F5431901-29AC-46D4-A717-DE2A9114E82D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Projbook.Extension.CSharpExtractor</RootNamespace>
<AssemblyName>Projbook.Extension.CSharpExtractor</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.1.37.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Reflection.Metadata, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Projbook\Extension\CSharp\CSharpExtractionMode.cs" />
<Compile Include="Projbook\Extension\CSharp\CSharpMatchingRule.cs" />
<Compile Include="Projbook\Extension\CSharp\CSharpSnippetExtractor.cs" />
<Compile Include="Projbook\Extension\CSharp\CSharpSyntaxMatchingNode.cs" />
<Compile Include="Projbook\Extension\CSharp\CSharpSyntaxWalkerMatchingBuilder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Projbook.Extension\Projbook.Extension.csproj">
<Project>{8338b756-0519-4d20-ba04-3a8f4839237a}</Project>
<Name>Projbook.Extension</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 0
- 23
src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpExtractionMode.cs View File

@@ -1,23 +0,0 @@
namespace Projbook.Extension.CSharpExtractor
{
/// <summary>
/// Represents the extraction mode.
/// </summary>
public enum CSharpExtractionMode
{
/// <summary>
/// Full member: Do not process the snippet and print it as it.
/// </summary>
FullMember,

/// <summary>
/// Content only: Extract the code block and print this part only.
/// </summary>
ContentOnly,

/// <summary>
/// Block structure only: Remove the block content and print the code structure only.
/// </summary>
BlockStructureOnly
}
}

+ 0
- 80
src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpMatchingRule.cs View File

@@ -1,80 +0,0 @@
using Projbook.Extension.Exception;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Projbook.Extension.CSharpExtractor
{
/// <summary>
/// Represents a matching rule for referencing a C# member.
/// </summary>
public class CSharpMatchingRule
{
/// <summary>
/// The matching chunk to identify which member are the snippet targets.
/// </summary>
public string[] MatchingChunks { get; private set; }

/// <summary>
/// The snippet extraction mode.
/// </summary>
public CSharpExtractionMode ExtractionMode { get; private set; }

/// <summary>
/// Defines rule regex used to parse the snippet into chunks.
/// Expected input format: Path/File.cs [My.Name.Space.Class.Method][(string, string)]
/// * The first chunk is the file name and will be loaded in <seealso cref="TargetFile"/>
/// * The optional second chunks are all full qualified name to the member separated by "."
/// * The optional last chunk is the method parameters if matching a method.
/// </summary>
private static Regex ruleRegex = new Regex(@"^([-=])?([^(]+)?\s*(\([^)]*\s*\))?\s*$", RegexOptions.Compiled);

/// <summary>
/// Parses the token
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
public static CSharpMatchingRule Parse(string pattern)
{
// Try to match the regex
pattern = Regex.Replace(pattern, @"\s", string.Empty);
Match match = CSharpMatchingRule.ruleRegex.Match(pattern);
if (!match.Success || string.IsNullOrWhiteSpace(match.Groups[0].Value))
{
throw new SnippetExtractionException("Invalid extraction rule", pattern);
}

// Retrieve values from the regex matching
string extractionOption = match.Groups[1].Value;
string rawMember = match.Groups[2].Value.Trim();
string rawParameters = match.Groups[3].Value.Trim();

// Build The matching chunk with extracted data
List<string> matchingChunks = new List<string>();
matchingChunks.AddRange(rawMember.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries));
if (rawParameters.Length >= 1)
{
matchingChunks.Add(rawParameters);
}

// Read extraction mode
CSharpExtractionMode extractionMode = CSharpExtractionMode.FullMember;
switch (extractionOption)
{
case "-":
extractionMode = CSharpExtractionMode.ContentOnly;
break;
case "=":
extractionMode = CSharpExtractionMode.BlockStructureOnly;
break;
}

// Build the matching rule based on the regex matching
return new CSharpMatchingRule
{
MatchingChunks = matchingChunks.ToArray(),
ExtractionMode = extractionMode
};
}
}
}

+ 0
- 368
src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSnippetExtractor.cs View File

@@ -1,368 +0,0 @@
using EnsureThat;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Projbook.Extension.Exception;
using Projbook.Extension.Spi;
using System;
using System.IO.Abstractions;
using System.Linq;
using System.Text;

namespace Projbook.Extension.CSharpExtractor
{
/// <summary>
/// Extractor in charge of browsing source directories. load file content and extract requested member.
/// </summary>
[Syntax(name: "csharp")]
public class CSharpSnippetExtractor : DefaultSnippetExtractor
{
/// <summary>
/// Represents the matching trie used for member matching.
/// Because of the cost of building the Trie, this value is lazy loaded and kept for future usages.
/// </summary>
private CSharpSyntaxMatchingNode syntaxTrie;

/// <summary>
/// Extracts a snippet from a given rule pattern.
/// </summary>
/// <param name="fileSystemInfo">The file system info.</param>
/// <param name="memberPattern">The member pattern to extract.</param>
/// <returns>The extracted snippet.</returns>
public override Model.Snippet Extract(FileSystemInfoBase fileSystemInfo, string memberPattern)
{
// Return the entire code if no member is specified
if (string.IsNullOrWhiteSpace(memberPattern))
{
return base.Extract(fileSystemInfo, memberPattern);
}

// Parse the matching rule from the pattern
CSharpMatchingRule rule = CSharpMatchingRule.Parse(memberPattern);

// Load the trie for pattern matching
if (null == this.syntaxTrie)
{
// Load file content
string sourceCode = base.LoadFile(this.ConvertToFile(fileSystemInfo));

// Build a syntax tree from the source code
SyntaxTree tree = CSharpSyntaxTree.ParseText(sourceCode);
SyntaxNode root = tree.GetRoot();

// Visit the syntax tree for generating a Trie for pattern matching
CSharpSyntaxWalkerMatchingBuilder syntaxMatchingBuilder = new CSharpSyntaxWalkerMatchingBuilder();
syntaxMatchingBuilder.Visit(root);

// Retrieve the Trie root
this.syntaxTrie = syntaxMatchingBuilder.Root;
}

// Match the rule from the syntax matching Trie
CSharpSyntaxMatchingNode matchingTrie = syntaxTrie.Match(rule.MatchingChunks);
if (null == matchingTrie)
{
throw new SnippetExtractionException("Cannot find member", memberPattern);
}

// Build a snippet for extracted syntax nodes
return this.BuildSnippet(matchingTrie.MatchingSyntaxNodes, rule.ExtractionMode);
}

/// <summary>
/// Builds a snippet from extracted syntax nodes.
/// </summary>
/// <param name="nodes">The exctracted nodes.</param>
/// <param name="extractionMode">The extraction mode.</param>
/// <returns>The built snippet.</returns>
private Model.Snippet BuildSnippet(SyntaxNode[] nodes, CSharpExtractionMode extractionMode)
{
// Data validation
Ensure.That(() => nodes).IsNotNull();
Ensure.That(() => nodes).HasItems();

// Extract code from each snippets
StringBuilder stringBuilder = new StringBuilder();
bool firstSnippet = true;
foreach (SyntaxNode node in nodes)
{
// Write line return between each snippet
if (!firstSnippet)
{
stringBuilder.AppendLine();
stringBuilder.AppendLine();
}
// Write each snippet line
string[] lines = node.GetText().Lines.Select(x => x.ToString()).ToArray();
int contentPosition = this.DetermineContentPosition(node);
this.WriteAndCleanupSnippet(stringBuilder, lines, extractionMode, contentPosition);

// Flag the first snippet as false
firstSnippet = false;
}
// Create the snippet from the exctracted code
return new Model.PlainTextSnippet(stringBuilder.ToString());
}

/// <summary>
/// Determines the content's block position depending on the node type.
/// </summary>
/// <param name="node">The node to extract the content position from.</param>
/// <returns>The determined content position or 0 if not found.</returns>
private int DetermineContentPosition(SyntaxNode node)
{
// Data validation
Ensure.That(() => node).IsNotNull();

// Select the content node element depending on the node type
TextSpan? contentTextSpan = null;
switch (node.Kind())
{
// Accessor list content
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.IndexerDeclaration:
case SyntaxKind.EventDeclaration:
AccessorListSyntax accessorList = node.DescendantNodes().OfType<AccessorListSyntax>().FirstOrDefault();
if (null != accessorList)
{
contentTextSpan = accessorList.FullSpan;
}
break;
// Contains children
case SyntaxKind.NamespaceDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ClassDeclaration:
SyntaxToken token = node.ChildTokens().Where(x => x.Kind() == SyntaxKind.OpenBraceToken).FirstOrDefault();
if (null != token)
{
contentTextSpan = token.FullSpan;
}
break;
// Block content
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.DestructorDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessorDeclaration:
case SyntaxKind.SetAccessorDeclaration:
case SyntaxKind.AddAccessorDeclaration:
case SyntaxKind.RemoveAccessorDeclaration:
BlockSyntax block = node.DescendantNodes().OfType<BlockSyntax>().FirstOrDefault();
if (null != block)
{
contentTextSpan = block.FullSpan;
}
break;
// Not processed by projbook csharp extractor
default:
break;
}

// Compute a line break insensitive position based on the fetched content text span if any is found
if (null != contentTextSpan)
{
int relativeTextSpanStart = contentTextSpan.Value.Start - node.FullSpan.Start;
return node
.ToFullString()
.Substring(0, relativeTextSpanStart)
.Replace("\r\n", "")
.Replace("\n", "").Length;
}

// Otherwise return 0 as default value
return 0;
}

/// <summary>
/// Writes and cleanup line snippets.
/// Snippets are moved out of their context, for this reason we need to trim lines aroung and remove a part of the indentation.
/// </summary>
/// <param name="stringBuilder">The string builder used as output.</param>
/// <param name="lines">The lines to process.</param>
/// <param name="extractionMode">The extraction mode.</param>
/// <param name="contentPosition">The content position.</param>
private void WriteAndCleanupSnippet(StringBuilder stringBuilder, string[] lines, CSharpExtractionMode extractionMode, int contentPosition)
{
// Data validation
Ensure.That(() => stringBuilder).IsNotNull();
Ensure.That(() => lines).IsNotNull();

// Do not process if lines are empty
if (0 >= lines.Length)
{
return;
}

// Compute the index of the first selected line
int startPos = 0;
int skippedCharNumber = 0;
if (CSharpExtractionMode.ContentOnly == extractionMode)
{
// Compute the content position index in the first processed line
int contentPositionFirstLineIndex = 0;
for (int totalLinePosition = 0; startPos < lines.Length; ++startPos)
{
// Compute the content position in the current line
string line = lines[startPos];
int relativePosition = contentPosition - totalLinePosition;
int contentPositionInLine = relativePosition < line.Length ? relativePosition: -1;

// In expected in the current line
if (contentPositionInLine >= 0)
{
// Look for the relative index in the current line
// Save the found index and break the iteration if any open bracket is found
int indexOf = line.IndexOf('{', contentPositionInLine);
if (0 <= indexOf)
{
contentPositionFirstLineIndex = indexOf;
break;
}
}

// Move the total line position after the processed line
totalLinePosition += lines[startPos].Length;
}

// Extract block code if any opening bracket has been found
if (startPos < lines.Length)
{
int openingBracketPos = lines[startPos].IndexOf('{', contentPositionFirstLineIndex);
if (openingBracketPos >= 0)
{
// Extract the code before the curly bracket
if (lines[startPos].Length > openingBracketPos)
{
lines[startPos] = lines[startPos].Substring(openingBracketPos + 1);
}

// Skip the current line if empty
if (string.IsNullOrWhiteSpace(lines[startPos]) && lines.Length > 1 + startPos)
{
++startPos;
}
}
}
}
else
{
// Skip leading whitespace lines and keep track of the amount of skipped char
for (; startPos < lines.Length; ++startPos)
{
// Break on non whitespace line
string line = lines[startPos];
if (line.Trim().Length > 0)
{
break;
}

// Record skipped char number
skippedCharNumber += line.Length;
}
}

// Compute the index of the lastselected line
int endPos = -1 + lines.Length;
if (CSharpExtractionMode.ContentOnly == extractionMode)
{
for (; 0 <= endPos && !lines[endPos].ToString().Contains('}'); --endPos);

// Extract block code if any closing bracket has been found
if (0 <= endPos)
{
int closingBracketPos = lines[endPos].IndexOf('}');
if (closingBracketPos >= 0)
{
// Extract the code before the curly bracket
if (lines[endPos].Length > closingBracketPos)
lines[endPos] = lines[endPos].Substring(0, closingBracketPos).TrimEnd();
}

// Skip the current line if empty
if (string.IsNullOrWhiteSpace(lines[endPos]) && lines.Length > -1 + endPos)
{
--endPos;
}
}
}
else
{
for (; 0 <= endPos && lines[endPos].ToString().Trim().Length == 0; --endPos);
}

// Compute the padding to remove for removing a part of the indentation
int leftPadding = int.MaxValue;
for (int i = startPos; i <= endPos; ++i)
{
// Ignore empty lines in the middle of the snippet
if (!string.IsNullOrWhiteSpace(lines[i]))
{
// Adjust the left padding with the available whitespace at the beginning of the line
leftPadding = Math.Min(leftPadding, lines[i].ToString().TakeWhile(Char.IsWhiteSpace).Count());
}
}

// Write selected lines to the string builder
bool firstLine = true;
for (int i = startPos; i <= endPos; ++i)
{
// Write line return between each line
if (!firstLine)
{
stringBuilder.AppendLine();
}

// Remove a part of the indentation padding
if (lines[i].Length > leftPadding)
{
string line = lines[i].Substring(leftPadding);

// Process the snippet depending on the extraction mode
switch (extractionMode)
{
// Extract the block structure only
case CSharpExtractionMode.BlockStructureOnly:

// Compute the content position in the current line
int relativePosition = contentPosition - skippedCharNumber;
int contentPositionInLine = relativePosition < line.Length + leftPadding ? relativePosition : -1;

// Look for open bracket from the content position in line
int openingBracketPos = -1;
if (contentPositionInLine >= 0)
{
openingBracketPos = line.IndexOf('{', Math.Max(0, contentPositionInLine - leftPadding));
}

// Anonymize code content if an open bracket is found
if (openingBracketPos >= 0)
{
// Extract the code before the curly bracket
if (line.Length > openingBracketPos)
line = line.Substring(0, 1 + openingBracketPos);

// Replace the content and close the block
line += string.Format("{0} // ...{0}}}", Environment.NewLine);

// Stop the iteration
endPos = i;
}
break;
}

// Append the line
stringBuilder.Append(line);
skippedCharNumber += lines[i].Length;
}
// Flag the first line as false
firstLine = false;
}
}
}
}

+ 0
- 201
src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxMatchingNode.cs View File

@@ -1,201 +0,0 @@
using EnsureThat;
using Microsoft.CodeAnalysis;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Projbook.Extension.CSharpExtractor
{
/// <summary>
/// Represents a syntax matching node.
/// Thie node is used to build a Trie representing possible matching.
/// Each node contians children and matching syntax nodes.
/// </summary>
public class CSharpSyntaxMatchingNode
{
/// <summary>
/// The public Matching SyntaxNodes.
/// </summary>
public SyntaxNode[] MatchingSyntaxNodes
{
get
{
// Return empty array id the nodes are empty
if (null == this.matchingSyntaxNodes)
{
return new SyntaxNode[0];
}

// Return the matching syntax nodes
return this.matchingSyntaxNodes.ToArray();
}
}

/// <summary>
/// The node's children.
/// </summary>
private Dictionary<string, CSharpSyntaxMatchingNode> children;

/// <summary>
/// The node's maching syntax node.
/// </summary>
private List<SyntaxNode> matchingSyntaxNodes;

/// <summary>
/// Finds a node from syntax chunk.
/// </summary>
/// <param name="chunks">The chunks to match.</param>
/// <returns></returns>
public CSharpSyntaxMatchingNode Match(string[] chunks)
{
// Data validation
Ensure.That(() => chunks).IsNotNull();

// Browse the Trie until finding a matching
CSharpSyntaxMatchingNode matchingNode = this;
foreach (string fragment in chunks)
{
// Could not find any matching
if (null == matchingNode.children || !matchingNode.children.TryGetValue(fragment, out matchingNode))
{
return null;
}
}

// Return the matching node
return matchingNode;
}

/// <summary>
/// Lookup a node from children and return it. if the node doesn't exist, a new one will be created and added to the children.
/// </summary>
/// <param name="name">The node name.</param>
/// <returns>The node matching the requested name.</returns>
public CSharpSyntaxMatchingNode EnsureNode(string name)
{
// Data validation
Ensure.That(() => name).IsNotNullOrWhiteSpace();

// Fetch a node from existing children and return it if any is found
CSharpSyntaxMatchingNode firstLevelNode;
if (null != this.children && this.children.TryGetValue(name, out firstLevelNode))
{
return firstLevelNode;
}

// Otherwise create a new node and return it
else
{
// Lazu create the dictionary for storing children
if (null == this.children)
{
this.children = new Dictionary<string, CSharpSyntaxMatchingNode>();
}

// Assign and return the new node
return this.children[name] = new CSharpSyntaxMatchingNode();
}
}

/// <summary>
/// Adds a syntax node as matching node.
/// </summary>
/// <param name="node"></param>
public void AddSyntaxNode(SyntaxNode node)
{
// Data validation
Ensure.That(() => node).IsNotNull();

// Lazy create the syntax node list
if (null == this.matchingSyntaxNodes)
{
this.matchingSyntaxNodes = new List<SyntaxNode>();
}
// Add the node to the known matching node
this.matchingSyntaxNodes.Add(node);
}

/// <summary>
/// Copies to a given node.
/// </summary>
/// <param name="targetNode">The node wherer to copy.</param>
/// <param name="name">The node name.</param>
public void CopyTo(CSharpSyntaxMatchingNode targetNode, string name)
{
// Data validation
Ensure.That(() => name).IsNotNullOrWhiteSpace();
Ensure.That(() => targetNode).IsNotNull();

// Ensure and retrieve a node the the copy
CSharpSyntaxMatchingNode newNode = targetNode.EnsureNode(name);
// Add syntax node to the created node
if (null != this.matchingSyntaxNodes)
{
// Lazy create the syntax nodes
if (null == newNode.matchingSyntaxNodes)
{
newNode.matchingSyntaxNodes = new List<SyntaxNode>();
}

// Merge syntax nodes
int[] indexes = newNode.matchingSyntaxNodes.Select(x => x.Span.Start).ToArray();
newNode.matchingSyntaxNodes.AddRange(this.matchingSyntaxNodes.Where(x => !indexes.Contains(x.Span.Start)));
}

// Recurse for applying copy to the children
if (null != this.children && this.children.Count > 0)
{
string[] childrenName = this.children.Keys.ToArray();
foreach (string childName in childrenName)
{
this.children[childName].CopyTo(newNode, childName);
}
}
}

/// <summary>
/// Overrides ToString to renger the internal Trie to a string.
/// </summary>
/// <returns>The rendered Trie as string.</returns>
public override string ToString()
{
StringBuilder strinbBuilder = new StringBuilder();
this.Write(strinbBuilder, null, 0);
return strinbBuilder.ToString();
}
/// <summary>
/// Writes a node to a string builder and recurse to the children.
/// </summary>
/// <param name="stringBuilder">The string builder used as output.</param>
/// <param name="name">The node name.</param>
/// <param name="level">The node level.</param>
private void Write(StringBuilder stringBuilder, string name, int level)
{
// Print the node only if the name is not null in order to ignore the root node for more clarity
int nextLevel = level;
if (null != name)
{
++nextLevel;
stringBuilder.AppendLine(string.Format("{0}{1}", new string('-', level), name));
}

// Print each matching syntax node
foreach (var matchingSyntaxNode in this.MatchingSyntaxNodes)
{
stringBuilder.AppendLine(string.Format("{0}[{1}]", new string('-', level), matchingSyntaxNode.GetType().Name));
}

// Recurse to children
if (null != this.children)
{
foreach (string childName in this.children.Keys)
{
this.children[childName].Write(stringBuilder, childName, nextLevel);
}
}
}
}
}

+ 0
- 329
src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxWalkerMatchingBuilder.cs View File

@@ -1,329 +0,0 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Linq;

namespace Projbook.Extension.CSharpExtractor
{
/// <summary>
/// Implements a syntax walker generating a Trie for pattern matching.
/// </summary>
public class CSharpSyntaxWalkerMatchingBuilder : CSharpSyntaxWalker
{
/// <summary>
/// The current Trie root available from the outside.
/// </summary>
public CSharpSyntaxMatchingNode Root { get; private set; }

/// <summary>
/// The Trie root referencing the root without any reference change.
/// </summary>
private CSharpSyntaxMatchingNode internalInvariantRoot;

/// <summary>
/// Initializes a new instance of <see cref="CSharpSyntaxWalkerMatchingBuilder"/>.
/// </summary>
public CSharpSyntaxWalkerMatchingBuilder()
{
this.internalInvariantRoot = new CSharpSyntaxMatchingNode();
this.Root = this.internalInvariantRoot;
}

/// <summary>
/// Visits a namespace declaration.
/// A namespace may be composed with different segment dot separated, each segment has to be represented by a different node.
/// However the syntax node is attached to the last node only.
/// </summary>
/// <param name="node">The namespace declaration node to visit.</param>
public override void VisitNamespaceDeclaration(NamespaceDeclarationSyntax node)
{
// Retrieve the namespace name and split segments
string name = node.Name.ToString();
string[] namespaces = name.Split('.');

// Keep track of the initial node the restore the root after the visit
CSharpSyntaxMatchingNode initialNode = this.Root;

// Browse all namespaces and generate intermediate node for each segment for the copy to the root
CSharpSyntaxMatchingNode firstNamespaceNode = null;
foreach (string currentNamespace in namespaces)
{
// Create the node and keep track of the first one
this.Root = this.Root.EnsureNode(currentNamespace);
if (null == firstNamespaceNode)
{
firstNamespaceNode = this.Root;
}
}

// Add the syntax node the last segment
this.Root.AddSyntaxNode(node);
// Triger member visiting
base.VisitNamespaceDeclaration(node);

// Copy the generated sub tree to the Trie root
firstNamespaceNode.CopyTo(this.internalInvariantRoot, namespaces[0]);

// Restore the initial root
this.Root = initialNode;
}

/// <summary>
/// Visits a class declaration.
/// </summary>
/// <param name="node">The class declaration to visit.</param>
public override void VisitClassDeclaration(ClassDeclarationSyntax node)
{
// Visit
this.Visit<ClassDeclarationSyntax>(
node: node,
typeParameterList: node.TypeParameterList,
exctractName: n => node.Identifier.ValueText,
targetNode: n => n,
visit: base.VisitClassDeclaration);
}

/// <summary>
/// Visits an interface declaration.
/// </summary>
/// <param name="node">The class declaration to visit.</param>
public override void VisitInterfaceDeclaration(InterfaceDeclarationSyntax node)
{
// Visit
this.Visit<InterfaceDeclarationSyntax>(
node: node,
typeParameterList: node.TypeParameterList,
exctractName: n => node.Identifier.ValueText,
targetNode: n => n,
visit: base.VisitInterfaceDeclaration);
}

/// <summary>
/// Visits an enum declaration.
/// </summary>
/// <param name="node">The enum declaration to visit.</param>
public override void VisitEnumDeclaration(EnumDeclarationSyntax node)
{
// Visit
this.Visit<EnumDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => node.Identifier.ValueText,
targetNode: n => n,
visit: base.VisitEnumDeclaration);
}


/// <summary>
/// Visits an enum member declaration.
/// </summary>
/// <param name="node">The enum member declaration to visit.</param>
public override void VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node)
{
// Visit
this.Visit<EnumMemberDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => node.Identifier.ValueText,
targetNode: n => n,
visit: base.VisitEnumMemberDeclaration);
}

/// <summary>
/// Visits a property declaration.
/// </summary>
/// <param name="node">The property declaration to visit.</param>
public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node)
{
// Visit
this.Visit<PropertyDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => n.Identifier.ValueText,
targetNode: n => n,
visit: base.VisitPropertyDeclaration);
}

/// <summary>
/// Visits a field declaration.
/// </summary>
/// <param name="node">The field declaration to visit.</param>
public override void VisitFieldDeclaration(FieldDeclarationSyntax node)
{
// Visit each variable declaration
foreach(VariableDeclaratorSyntax variableDeclarationSyntax in node.Declaration.Variables)
{
this.Visit<FieldDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => variableDeclarationSyntax.Identifier.ValueText,
targetNode: n => n,
visit: base.VisitFieldDeclaration);
}
}

/// <summary>
/// Visits an indexter declaration.
/// </summary>
/// <param name="node">The indexter declaration to visit.</param>
public override void VisitIndexerDeclaration(IndexerDeclarationSyntax node)
{
// Compute suffix for representing generics
string memberName = string.Empty;
if (null != node.ParameterList)
{
memberName = string.Format(
"[{0}]",
string.Join(",", node.ParameterList.Parameters.Select(x => x.Type.ToString())));
}

// Visit
this.Visit<IndexerDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => memberName,
targetNode: n => n,
visit: base.VisitIndexerDeclaration);
}

/// <summary>
/// Visits an event declaration.
/// </summary>
/// <param name="node">The event declaration to visit.</param>
public override void VisitEventDeclaration(EventDeclarationSyntax node)
{
// Visit
this.Visit<EventDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => n.Identifier.ValueText,
targetNode: n => n,
visit: base.VisitEventDeclaration);
}

/// <summary>
/// Visits an accessor declaration.
/// </summary>
/// <param name="node">The accessor declaration to visit.</param>
public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node)
{
// Visit
this.Visit<AccessorDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => n.Keyword.ValueText,
targetNode: n => n,
visit: base.VisitAccessorDeclaration);
}

/// <summary>
/// Visits a method declaration.
/// </summary>
/// <param name="node">The method declaration to visit.</param>
public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
{
// Visit
this.Visit<MethodDeclarationSyntax>(
node: node,
typeParameterList: node.TypeParameterList,
exctractName: n => n.Identifier.ValueText,
targetNode: n => n,
visit: base.VisitMethodDeclaration);
}

/// <summary>
/// Visits a constructor declaration.
/// </summary>
/// <param name="node">The constructor declaration to visit.</param>
public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
{
// Visit
this.Visit<ConstructorDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => "<Constructor>",
targetNode: n => n,
visit: base.VisitConstructorDeclaration);
}

/// <summary>
/// Visits a destructor declaration.
/// </summary>
/// <param name="node">The destructor declaration to visit.</param>
public override void VisitDestructorDeclaration(DestructorDeclarationSyntax node)
{
// Visit
this.Visit<DestructorDeclarationSyntax>(
node: node,
typeParameterList: null,
exctractName: n => "<Destructor>",
targetNode: n => n,
visit: base.VisitDestructorDeclaration);
}

/// <summary>
/// Visits parameter list.
/// </summary>
/// <param name="node">The parameter list to visit.</param>
public override void VisitParameterList(ParameterListSyntax node)
{
// Skip parameter list when the parent is a lambda
if (
SyntaxKind.SimpleLambdaExpression == node.Parent.Kind() ||
SyntaxKind.ParenthesizedLambdaExpression == node.Parent.Kind())
{
return;
}

// Visit
this.Visit<ParameterListSyntax>(
node: node,
typeParameterList: null,
exctractName: n => string.Format("({0})", string.Join(",", node.Parameters.Select(x => x.Type.ToString()))),
targetNode: n => n.Parent,
visit: base.VisitParameterList);
}

/// <summary>
/// Visits a member.
/// </summary>
/// <typeparam name="T">The syntax node type to visit.</typeparam>
/// <param name="node">The node to visit.</param>
/// <param name="exctractName">Extract the node name.</param>
/// <param name="typeParameterList">The type parameter list.</param>
/// <param name="targetNode">Resolved the target node.</param>
/// <param name="visit">Visit sub nodes.</param>
private void Visit<T>(T node, Func<T, string> exctractName, TypeParameterListSyntax typeParameterList , Func<T, SyntaxNode> targetNode, Action<T> visit) where T : CSharpSyntaxNode
{
// Retrieve the accessor name
string name = exctractName(node);

// Compute suffix for representing generics
if (null != typeParameterList)
{
name = string.Format(
"{0}{{{1}}}",
name,
string.Join(",", typeParameterList.Parameters.Select(x => x.ToString())));
}
// Keep track of the initial node the restore the root after the visit
CSharpSyntaxMatchingNode initialNode = this.Root;

// Create and add the node
this.Root = this.Root.EnsureNode(name);
this.Root.AddSyntaxNode(targetNode(node));

// Trigger member visiting
visit(node);

// Copy the class sub tree to the Trie root
this.Root.CopyTo(this.internalInvariantRoot, name);

// Restore the initial root
this.Root = initialNode;
}
}
}

+ 0
- 36
src/Projbook.Extension.CSharpExtractor/Properties/AssemblyInfo.cs View File

@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Projbook.Extension.CSharpExtractor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Projbook.Extension.CSharpExtractor")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f5431901-29ac-46d4-a717-de2a9114e82d")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 0
- 9
src/Projbook.Extension.CSharpExtractor/packages.config View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.Common" version="1.3.2" targetFramework="net45" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.3.2" targetFramework="net45" />
<package id="System.Collections.Immutable" version="1.1.37" targetFramework="net45" />
<package id="System.IO.Abstractions" version="2.0.0.136" targetFramework="net45" />
<package id="System.Reflection.Metadata" version="1.2.0" targetFramework="net45" />
</packages>

+ 0
- 68
src/Projbook.Extension.XmlExtractor/Projbook.Extension.XmlExtractor.csproj View File

@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BC3E43EB-2263-49B4-883A-B720EDDF9298}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Projbook.Extension.XmlExtractor</RootNamespace>
<AssemblyName>Projbook.Extension.XmlExtractor</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Abstractions, Version=2.0.0.136, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Abstractions.2.0.0.136\lib\net40\System.IO.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Projbook\Extension\Xml\XmlSnippetExtractor.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Projbook.Extension\Projbook.Extension.csproj">
<Project>{8338b756-0519-4d20-ba04-3a8f4839237a}</Project>
<Name>Projbook.Extension</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 0
- 159
src/Projbook.Extension.XmlExtractor/Projbook/Extension/Xml/XmlSnippetExtractor.cs View File

@@ -1,159 +0,0 @@
using System;
using Projbook.Extension.Exception;
using Projbook.Extension.Spi;
using System.IO.Abstractions;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace Projbook.Extension.XmlExtractor
{
/// <summary>
/// Extractor in charge of browsing source directories. load file content and extract requested member.
/// </summary>
[Syntax(name: "xml")]
public class XmlSnippetExtractor : DefaultSnippetExtractor
{
/// <summary>
/// The regex extracting the document namespaces
/// </summary>
private Regex regex = new Regex(@"xmlns:([^=]+)=""([^""]*)""", RegexOptions.Compiled);
/// <summary>
/// The lazy loaded xml document.
/// </summary>
private XmlDocument xmlDocument;

/// <summary>
/// The lazy loaded namespace manager.
/// </summary>
private XmlNamespaceManager xmlNamespaceManager;

/// <summary>
/// Extracts a snippet from a given rule pattern.
/// </summary>
/// <param name="fileSystemInfo">The file system info.</param>
/// <param name="memberPattern">The member pattern to extract.</param>
/// <returns>The extracted snippet.</returns>
public override Extension.Model.Snippet Extract(FileSystemInfoBase fileSystemInfo, string memberPattern)
{
// Return the entire code if no member is specified
if (string.IsNullOrWhiteSpace(memberPattern))
{
return base.Extract(fileSystemInfo, memberPattern);
}

// Load the xml document for xpath execution
if (null == this.xmlDocument)
{
// Load file content
string sourceCode = base.LoadFile(this.ConvertToFile(fileSystemInfo));

// Remove default avoiding to define and use a prefix for the default namespace
// This is not strictly correct in a xml point of view but it's closest to most needs
sourceCode = Regex.Replace(sourceCode, @"xmlns\s*=\s*""[^""]*""", string.Empty);
// Parse the file as xml
this.xmlDocument = new XmlDocument();
try
{
// Initialize the document and the namespace manager
this.xmlDocument.LoadXml(sourceCode);
this.xmlNamespaceManager = new XmlNamespaceManager(this.xmlDocument.NameTable);
// Match namespace declaration for filling the namespace manager
Match match = this.regex.Match(sourceCode);
while (match.Success)
{
// Collect prefix and namespace value
string prefix = match.Groups[1].Value.Trim();
string ns = match.Groups[2].Value.Trim();
// Add namespace declaration to the namespace manager
xmlNamespaceManager.AddNamespace(prefix, ns);

// Mode to the next matching
match = match.NextMatch();
}
}

// Throw an exception is the file is not loadable as xml document
catch (System.Exception exception)
{
throw new SnippetExtractionException("Cannot parse xml file", exception.Message);
}
}

// Execute Xpath query
XmlNodeList xmlNodeList = null;
try
{
xmlNodeList = this.xmlDocument.SelectNodes(memberPattern, this.xmlNamespaceManager);
}
catch
{
throw new SnippetExtractionException("Invalid extraction rule", memberPattern);
}
// Ensure we found a result
if (xmlNodeList.Count <= 0)
{
throw new SnippetExtractionException("Cannot find member", memberPattern);
}
// Build a snippet for extracted nodes
return this.BuildSnippet(xmlNodeList);
}
/// <summary>
/// Builds a snippet from xml node.
/// </summary>
/// <param name="xmlNodeList">The xml node list.</param>
/// <returns>The built snippet.</returns>
private Extension.Model.Snippet BuildSnippet(XmlNodeList xmlNodeList)
{
// Data validation
if(xmlNodeList == null)
{
throw new ArgumentNullException(nameof(xmlNodeList));
}

// Extract code from each snippets
StringBuilder stringBuilder = new StringBuilder();
bool firstSnippet = true;
for (int i = 0; i < xmlNodeList.Count; ++i)
{
// Get the current node
XmlNode node = xmlNodeList.Item(i);

// Write line return between each snippet
if (!firstSnippet)
{
stringBuilder.AppendLine();
stringBuilder.AppendLine();
}

// Write each snippet
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
settings.NewLineOnAttributes = true;
using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, settings))
{
node.WriteTo(xmlWriter);
}

// Flag the first snippet as false
firstSnippet = false;
}

// Remove all generate namespace declaration
// This is produce some output lacking of namespace declaration but it's what is relevant for a xml document extraction
string output = stringBuilder.ToString();
output = Regex.Replace(output, @" ?xmlns\s*(:[^=]+)?\s*=\s*""[^""]*""", string.Empty);

// Create the snippet from the extracted code
return new Model.PlainTextSnippet(output);
}
}
}

+ 0
- 36
src/Projbook.Extension.XmlExtractor/Properties/AssemblyInfo.cs View File

@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Projbook.Extension.XmlExtractor")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Projbook.Extension.XmlExtractor")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("bc3e43eb-2263-49b4-883a-b720eddf9298")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 0
- 5
src/Projbook.Extension.XmlExtractor/packages.config View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Ensure.That" version="5.0.0" targetFramework="net45" />
<package id="System.IO.Abstractions" version="2.0.0.136" targetFramework="net45" />
</packages>

+ 2
- 2
src/Projbook.Extension/Exception/SnippetExtractionException.cs View File

@@ -11,9 +11,9 @@
public string Pattern { get; private set; }

/// <summary>
/// Initializes a new instance of <see cref="ProjbookEngine"/>.
/// Initializes a new instance of <see cref="SnippetExtractionException"/>.
/// </summary>
/// <param name="message">Initializes the required <see cref="Message"/>.</param>
/// <param name="message">Initializes the required message.</param>
/// <param name="pattern">Initializes the required <see cref="Pattern"/>.</param>
public SnippetExtractionException(string message, string pattern)
: base(message)


+ 1
- 1
src/Projbook.Extension/Extractors/CSharp/CSharpMatchingRule.cs View File

@@ -23,7 +23,7 @@ namespace Projbook.Extension.CSharpExtractor
/// <summary>
/// Defines rule regex used to parse the snippet into chunks.
/// Expected input format: Path/File.cs [My.Name.Space.Class.Method][(string, string)]
/// * The first chunk is the file name and will be loaded in <seealso cref="TargetFile"/>
/// * The first chunk is the file name and will be loaded in TargetFile
/// * The optional second chunks are all full qualified name to the member separated by "."
/// * The optional last chunk is the method parameters if matching a method.
/// </summary>


+ 6
- 4
src/Projbook.Extension/Projbook.Extension.csproj View File

@@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Projbook.Extension.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -40,14 +41,15 @@
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.1.37.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll</HintPath>
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Reflection.Metadata, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
<Reference Include="System.Reflection.Metadata, Version=1.4.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reflection.Metadata.1.4.1\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Threading.Thread, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">


+ 6
- 6
src/Projbook.Extension/app.config View File

@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0"/>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.1.0" newVersion="1.4.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0"/>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" /></startup></configuration>

+ 10
- 10
src/Projbook.Extension/packages.config View File

@@ -3,14 +3,14 @@
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net451" />
<package id="Microsoft.CodeAnalysis.Common" version="1.3.2" targetFramework="net451" />
<package id="Microsoft.CodeAnalysis.CSharp" version="1.3.2" targetFramework="net451" />
<package id="System.Collections" version="4.0.0" targetFramework="net451" />
<package id="System.Collections.Immutable" version="1.1.37" targetFramework="net451" />
<package id="System.Diagnostics.Debug" version="4.0.0" targetFramework="net451" />
<package id="System.Globalization" version="4.0.0" targetFramework="net451" />
<package id="System.Linq" version="4.0.0" targetFramework="net451" />
<package id="System.Reflection.Metadata" version="1.2.0" targetFramework="net451" />
<package id="System.Resources.ResourceManager" version="4.0.0" targetFramework="net451" />
<package id="System.Runtime" version="4.0.0" targetFramework="net451" />
<package id="System.Runtime.Extensions" version="4.0.0" targetFramework="net451" />
<package id="System.Threading" version="4.0.0" targetFramework="net451" />
<package id="System.Collections" version="4.3.0" targetFramework="net451" />
<package id="System.Collections.Immutable" version="1.3.0" targetFramework="net451" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net451" />
<package id="System.Globalization" version="4.3.0" targetFramework="net451" />
<package id="System.Linq" version="4.3.0" targetFramework="net451" />
<package id="System.Reflection.Metadata" version="1.4.1" targetFramework="net451" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net451" />
<package id="System.Runtime" version="4.3.0" targetFramework="net451" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net451" />
<package id="System.Threading" version="4.3.0" targetFramework="net451" />
</packages>

Loading…
Cancel
Save