diff --git a/src/DocNet/App.config b/src/DocNet/App.config index 5893e9a..4e41c21 100644 --- a/src/DocNet/App.config +++ b/src/DocNet/App.config @@ -7,11 +7,11 @@ - + - + diff --git a/src/DocNet/Docnet.csproj b/src/DocNet/Docnet.csproj index 062811f..ff52d74 100644 --- a/src/DocNet/Docnet.csproj +++ b/src/DocNet/Docnet.csproj @@ -33,11 +33,15 @@ 4 - - ..\..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll True + + ..\..\packages\System.Collections.Immutable.1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + True + @@ -72,6 +76,9 @@ MarkdownDeep + + + - \ No newline at end of file diff --git a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpExtractionMode.cs b/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpExtractionMode.cs deleted file mode 100644 index 1cb6291..0000000 --- a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpExtractionMode.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Projbook.Extension.CSharpExtractor -{ - /// - /// Represents the extraction mode. - /// - public enum CSharpExtractionMode - { - /// - /// Full member: Do not process the snippet and print it as it. - /// - FullMember, - - /// - /// Content only: Extract the code block and print this part only. - /// - ContentOnly, - - /// - /// Block structure only: Remove the block content and print the code structure only. - /// - BlockStructureOnly - } -} \ No newline at end of file diff --git a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpMatchingRule.cs b/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpMatchingRule.cs deleted file mode 100644 index 6d6c221..0000000 --- a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpMatchingRule.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Projbook.Extension.Exception; -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; - -namespace Projbook.Extension.CSharpExtractor -{ - /// - /// Represents a matching rule for referencing a C# member. - /// - public class CSharpMatchingRule - { - /// - /// The matching chunk to identify which member are the snippet targets. - /// - public string[] MatchingChunks { get; private set; } - - /// - /// The snippet extraction mode. - /// - public CSharpExtractionMode ExtractionMode { get; private set; } - - /// - /// 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 - /// * 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. - /// - private static Regex ruleRegex = new Regex(@"^([-=])?([^(]+)?\s*(\([^)]*\s*\))?\s*$", RegexOptions.Compiled); - - /// - /// Parses the token - /// - /// - /// - 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 matchingChunks = new List(); - 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 - }; - } - } -} \ No newline at end of file diff --git a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSnippetExtractor.cs b/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSnippetExtractor.cs deleted file mode 100644 index bca6ae1..0000000 --- a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSnippetExtractor.cs +++ /dev/null @@ -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 -{ - /// - /// Extractor in charge of browsing source directories. load file content and extract requested member. - /// - [Syntax(name: "csharp")] - public class CSharpSnippetExtractor : DefaultSnippetExtractor - { - /// - /// 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. - /// - private CSharpSyntaxMatchingNode syntaxTrie; - - /// - /// Extracts a snippet from a given rule pattern. - /// - /// The file system info. - /// The member pattern to extract. - /// The extracted snippet. - 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); - } - - /// - /// Builds a snippet from extracted syntax nodes. - /// - /// The exctracted nodes. - /// The extraction mode. - /// The built snippet. - 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()); - } - - /// - /// Determines the content's block position depending on the node type. - /// - /// The node to extract the content position from. - /// The determined content position or 0 if not found. - 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().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().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; - } - - /// - /// 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. - /// - /// The string builder used as output. - /// The lines to process. - /// The extraction mode. - /// The content position. - 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; - } - } - } -} \ No newline at end of file diff --git a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxMatchingNode.cs b/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxMatchingNode.cs deleted file mode 100644 index 9f1b33a..0000000 --- a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxMatchingNode.cs +++ /dev/null @@ -1,201 +0,0 @@ -using EnsureThat; -using Microsoft.CodeAnalysis; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Projbook.Extension.CSharpExtractor -{ - /// - /// Represents a syntax matching node. - /// Thie node is used to build a Trie representing possible matching. - /// Each node contians children and matching syntax nodes. - /// - public class CSharpSyntaxMatchingNode - { - /// - /// The public Matching SyntaxNodes. - /// - 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(); - } - } - - /// - /// The node's children. - /// - private Dictionary children; - - /// - /// The node's maching syntax node. - /// - private List matchingSyntaxNodes; - - /// - /// Finds a node from syntax chunk. - /// - /// The chunks to match. - /// - 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; - } - - /// - /// 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. - /// - /// The node name. - /// The node matching the requested name. - 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(); - } - - // Assign and return the new node - return this.children[name] = new CSharpSyntaxMatchingNode(); - } - } - - /// - /// Adds a syntax node as matching node. - /// - /// - 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(); - } - - // Add the node to the known matching node - this.matchingSyntaxNodes.Add(node); - } - - /// - /// Copies to a given node. - /// - /// The node wherer to copy. - /// The node name. - 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(); - } - - // 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); - } - } - } - - /// - /// Overrides ToString to renger the internal Trie to a string. - /// - /// The rendered Trie as string. - public override string ToString() - { - StringBuilder strinbBuilder = new StringBuilder(); - this.Write(strinbBuilder, null, 0); - return strinbBuilder.ToString(); - } - - /// - /// Writes a node to a string builder and recurse to the children. - /// - /// The string builder used as output. - /// The node name. - /// The node level. - 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); - } - } - } - } -} \ No newline at end of file diff --git a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxWalkerMatchingBuilder.cs b/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxWalkerMatchingBuilder.cs deleted file mode 100644 index d6a72f1..0000000 --- a/src/Projbook.Extension.CSharpExtractor/Projbook/Extension/CSharp/CSharpSyntaxWalkerMatchingBuilder.cs +++ /dev/null @@ -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 -{ - /// - /// Implements a syntax walker generating a Trie for pattern matching. - /// - public class CSharpSyntaxWalkerMatchingBuilder : CSharpSyntaxWalker - { - /// - /// The current Trie root available from the outside. - /// - public CSharpSyntaxMatchingNode Root { get; private set; } - - /// - /// The Trie root referencing the root without any reference change. - /// - private CSharpSyntaxMatchingNode internalInvariantRoot; - - /// - /// Initializes a new instance of . - /// - public CSharpSyntaxWalkerMatchingBuilder() - { - this.internalInvariantRoot = new CSharpSyntaxMatchingNode(); - this.Root = this.internalInvariantRoot; - } - - /// - /// 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. - /// - /// The namespace declaration node to visit. - 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; - } - - /// - /// Visits a class declaration. - /// - /// The class declaration to visit. - public override void VisitClassDeclaration(ClassDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: node.TypeParameterList, - exctractName: n => node.Identifier.ValueText, - targetNode: n => n, - visit: base.VisitClassDeclaration); - } - - /// - /// Visits an interface declaration. - /// - /// The class declaration to visit. - public override void VisitInterfaceDeclaration(InterfaceDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: node.TypeParameterList, - exctractName: n => node.Identifier.ValueText, - targetNode: n => n, - visit: base.VisitInterfaceDeclaration); - } - - /// - /// Visits an enum declaration. - /// - /// The enum declaration to visit. - public override void VisitEnumDeclaration(EnumDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: null, - exctractName: n => node.Identifier.ValueText, - targetNode: n => n, - visit: base.VisitEnumDeclaration); - } - - - /// - /// Visits an enum member declaration. - /// - /// The enum member declaration to visit. - public override void VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: null, - exctractName: n => node.Identifier.ValueText, - targetNode: n => n, - visit: base.VisitEnumMemberDeclaration); - } - - /// - /// Visits a property declaration. - /// - /// The property declaration to visit. - public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: null, - exctractName: n => n.Identifier.ValueText, - targetNode: n => n, - visit: base.VisitPropertyDeclaration); - } - - /// - /// Visits a field declaration. - /// - /// The field declaration to visit. - public override void VisitFieldDeclaration(FieldDeclarationSyntax node) - { - // Visit each variable declaration - foreach(VariableDeclaratorSyntax variableDeclarationSyntax in node.Declaration.Variables) - { - this.Visit( - node: node, - typeParameterList: null, - exctractName: n => variableDeclarationSyntax.Identifier.ValueText, - targetNode: n => n, - visit: base.VisitFieldDeclaration); - } - } - - /// - /// Visits an indexter declaration. - /// - /// The indexter declaration to visit. - 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( - node: node, - typeParameterList: null, - exctractName: n => memberName, - targetNode: n => n, - visit: base.VisitIndexerDeclaration); - } - - /// - /// Visits an event declaration. - /// - /// The event declaration to visit. - public override void VisitEventDeclaration(EventDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: null, - exctractName: n => n.Identifier.ValueText, - targetNode: n => n, - visit: base.VisitEventDeclaration); - } - - /// - /// Visits an accessor declaration. - /// - /// The accessor declaration to visit. - public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: null, - exctractName: n => n.Keyword.ValueText, - targetNode: n => n, - visit: base.VisitAccessorDeclaration); - } - - /// - /// Visits a method declaration. - /// - /// The method declaration to visit. - public override void VisitMethodDeclaration(MethodDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: node.TypeParameterList, - exctractName: n => n.Identifier.ValueText, - targetNode: n => n, - visit: base.VisitMethodDeclaration); - } - - /// - /// Visits a constructor declaration. - /// - /// The constructor declaration to visit. - public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: null, - exctractName: n => "", - targetNode: n => n, - visit: base.VisitConstructorDeclaration); - } - - /// - /// Visits a destructor declaration. - /// - /// The destructor declaration to visit. - public override void VisitDestructorDeclaration(DestructorDeclarationSyntax node) - { - // Visit - this.Visit( - node: node, - typeParameterList: null, - exctractName: n => "", - targetNode: n => n, - visit: base.VisitDestructorDeclaration); - } - - /// - /// Visits parameter list. - /// - /// The parameter list to visit. - 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( - 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); - } - - /// - /// Visits a member. - /// - /// The syntax node type to visit. - /// The node to visit. - /// Extract the node name. - /// The type parameter list. - /// Resolved the target node. - /// Visit sub nodes. - private void Visit(T node, Func exctractName, TypeParameterListSyntax typeParameterList , Func targetNode, Action 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; - } - } -} \ No newline at end of file diff --git a/src/Projbook.Extension.CSharpExtractor/Properties/AssemblyInfo.cs b/src/Projbook.Extension.CSharpExtractor/Properties/AssemblyInfo.cs deleted file mode 100644 index d9a7916..0000000 --- a/src/Projbook.Extension.CSharpExtractor/Properties/AssemblyInfo.cs +++ /dev/null @@ -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")] diff --git a/src/Projbook.Extension.CSharpExtractor/packages.config b/src/Projbook.Extension.CSharpExtractor/packages.config deleted file mode 100644 index ecf5663..0000000 --- a/src/Projbook.Extension.CSharpExtractor/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/Projbook.Extension.XmlExtractor/Projbook.Extension.XmlExtractor.csproj b/src/Projbook.Extension.XmlExtractor/Projbook.Extension.XmlExtractor.csproj deleted file mode 100644 index 1e600b5..0000000 --- a/src/Projbook.Extension.XmlExtractor/Projbook.Extension.XmlExtractor.csproj +++ /dev/null @@ -1,68 +0,0 @@ - - - - - Debug - AnyCPU - {BC3E43EB-2263-49B4-883A-B720EDDF9298} - Library - Properties - Projbook.Extension.XmlExtractor - Projbook.Extension.XmlExtractor - v4.6.1 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - ..\packages\System.IO.Abstractions.2.0.0.136\lib\net40\System.IO.Abstractions.dll - True - - - - - - - - - - - - - - - {8338b756-0519-4d20-ba04-3a8f4839237a} - Projbook.Extension - - - - - - - - \ No newline at end of file diff --git a/src/Projbook.Extension.XmlExtractor/Projbook/Extension/Xml/XmlSnippetExtractor.cs b/src/Projbook.Extension.XmlExtractor/Projbook/Extension/Xml/XmlSnippetExtractor.cs deleted file mode 100644 index 71fd51a..0000000 --- a/src/Projbook.Extension.XmlExtractor/Projbook/Extension/Xml/XmlSnippetExtractor.cs +++ /dev/null @@ -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 -{ - /// - /// Extractor in charge of browsing source directories. load file content and extract requested member. - /// - [Syntax(name: "xml")] - public class XmlSnippetExtractor : DefaultSnippetExtractor - { - /// - /// The regex extracting the document namespaces - /// - private Regex regex = new Regex(@"xmlns:([^=]+)=""([^""]*)""", RegexOptions.Compiled); - - /// - /// The lazy loaded xml document. - /// - private XmlDocument xmlDocument; - - /// - /// The lazy loaded namespace manager. - /// - private XmlNamespaceManager xmlNamespaceManager; - - /// - /// Extracts a snippet from a given rule pattern. - /// - /// The file system info. - /// The member pattern to extract. - /// The extracted snippet. - 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); - } - - /// - /// Builds a snippet from xml node. - /// - /// The xml node list. - /// The built snippet. - 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); - } - } -} \ No newline at end of file diff --git a/src/Projbook.Extension.XmlExtractor/Properties/AssemblyInfo.cs b/src/Projbook.Extension.XmlExtractor/Properties/AssemblyInfo.cs deleted file mode 100644 index 35cf6c0..0000000 --- a/src/Projbook.Extension.XmlExtractor/Properties/AssemblyInfo.cs +++ /dev/null @@ -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")] diff --git a/src/Projbook.Extension.XmlExtractor/packages.config b/src/Projbook.Extension.XmlExtractor/packages.config deleted file mode 100644 index 0ff97ab..0000000 --- a/src/Projbook.Extension.XmlExtractor/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/Projbook.Extension/Exception/SnippetExtractionException.cs b/src/Projbook.Extension/Exception/SnippetExtractionException.cs index e1ded67..3f04cd3 100644 --- a/src/Projbook.Extension/Exception/SnippetExtractionException.cs +++ b/src/Projbook.Extension/Exception/SnippetExtractionException.cs @@ -11,9 +11,9 @@ public string Pattern { get; private set; } /// - /// Initializes a new instance of . + /// Initializes a new instance of . /// - /// Initializes the required . + /// Initializes the required message. /// Initializes the required . public SnippetExtractionException(string message, string pattern) : base(message) diff --git a/src/Projbook.Extension/Extractors/CSharp/CSharpMatchingRule.cs b/src/Projbook.Extension/Extractors/CSharp/CSharpMatchingRule.cs index 6d6c221..5c94083 100644 --- a/src/Projbook.Extension/Extractors/CSharp/CSharpMatchingRule.cs +++ b/src/Projbook.Extension/Extractors/CSharp/CSharpMatchingRule.cs @@ -23,7 +23,7 @@ namespace Projbook.Extension.CSharpExtractor /// /// 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 + /// * 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. /// diff --git a/src/Projbook.Extension/Projbook.Extension.csproj b/src/Projbook.Extension/Projbook.Extension.csproj index c5757f9..47be8d1 100644 --- a/src/Projbook.Extension/Projbook.Extension.csproj +++ b/src/Projbook.Extension/Projbook.Extension.csproj @@ -21,6 +21,7 @@ DEBUG;TRACE prompt 4 + bin\Debug\Projbook.Extension.XML pdbonly @@ -40,14 +41,15 @@ True - - ..\..\packages\System.Collections.Immutable.1.1.37\lib\dotnet\System.Collections.Immutable.dll + + ..\..\packages\System.Collections.Immutable.1.3.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll True + - - ..\..\packages\System.Reflection.Metadata.1.2.0\lib\portable-net45+win8\System.Reflection.Metadata.dll + + ..\..\packages\System.Reflection.Metadata.1.4.1\lib\portable-net45+win8\System.Reflection.Metadata.dll True diff --git a/src/Projbook.Extension/app.config b/src/Projbook.Extension/app.config index a11801f..a165e54 100644 --- a/src/Projbook.Extension/app.config +++ b/src/Projbook.Extension/app.config @@ -1,15 +1,15 @@ - + - - + + - - + + - + diff --git a/src/Projbook.Extension/packages.config b/src/Projbook.Extension/packages.config index b851084..258b0f6 100644 --- a/src/Projbook.Extension/packages.config +++ b/src/Projbook.Extension/packages.config @@ -3,14 +3,14 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file