├── .editorconfig
├── .gitignore
├── LICENSE.txt
├── NuGet.config
├── Publish.ps1
├── README.md
├── ZenSharp.Core
├── GenerateTree.n
├── LiveTemplateMatcher.n
├── Parser
│ ├── ConcatRule.n
│ ├── ErrorContextLocator.n
│ ├── LeafRule.n
│ ├── LtgParser.n
│ ├── ParsingException.n
│ ├── Rule.n
│ └── TreePart.n
├── Properties
│ └── AssemblyInfo.n
├── Utils
│ ├── Identifier.n
│ ├── ListExtensions.n
│ ├── MultiDict.n
│ └── RuleFactory.n
├── ZenSharp.Core.Tests
│ ├── Data
│ │ └── jack.ltg
│ ├── Doc
│ │ └── RailroadGenerator.cs
│ ├── ExpandTestGenerator.cs
│ ├── ExpandTestGenerator.tt
│ ├── GetContextTests.cs
│ ├── LeafRulesMatchTest.cs
│ ├── LiveTemplateMatcherTests.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── TestParser.cs
│ ├── ZenSharp.Core.Tests.csproj
│ └── packages.config
├── ZenSharp.Core.nproj
├── build.bat
└── ltg.vim
├── ZenSharp.Integration
├── CSharpExtendedScopeProvider.cs
├── EditConfigActionHandler.cs
├── Extension
│ ├── LeafSubstitution.cs
│ └── MatchResultExtension.cs
├── LtgConfigWatcher.cs
├── Option
│ ├── ExceptionConverter.cs
│ ├── ZenSettingsPage.xaml
│ └── ZenSettingsPage.xaml.cs
├── Templates.ltg
├── ZenSharp.Integration.csproj
├── ZenSharpItemsProvider.cs
├── ZenSharpLookupItem.cs
├── ZenSharpSettings.cs
├── ZoneMarker.cs
├── app.config
└── resharper_macros.71.txt
├── ZenSharp.nuspec
├── ZenSharp.sln
├── build.bat
├── buildNuPack.ps1
├── dependencies.json
├── doc
├── railroad-diagrams.css
├── railroad-diagrams.js
├── sample.html
├── screen1.gif
└── screen2.gif
└── patchAssemblyInfo.ps1
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | insert_final_newline = true
6 |
7 | [*.cs]
8 | indent_size = 4
9 |
10 | [*.{js,ts}]
11 | indent_size = 4
12 |
13 | [*.{xml,csproj,targets,props,nuspec,resx}]
14 | indent_size = 2
15 |
16 | [*.json]
17 | indent_size = 2
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | #ignore thumbnails created by windows
3 | Thumbs.db
4 | #Ignore files build by Visual Studio
5 |
6 | *.obj
7 | *.exe
8 | *.pdb
9 | *.user
10 | *.aps
11 | *.pch
12 | *.vspscc
13 | *_i.c
14 | *_p.c
15 | *.ncb
16 | *.suo
17 | *.tlb
18 | *.tlh
19 | *.bak
20 | *.cache
21 | *.ilk
22 | *.log
23 | [Bb]in
24 | [Dd]ebug*/
25 | *.lib
26 | *.sbr
27 | obj/
28 | [Rr]elease*/
29 | _ReSharper*/
30 | [Tt]est[Rr]esult*
31 | packages/
32 | doc/out.html
33 |
34 | #other
35 | .vs
36 | .idea
37 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright Alexander Ulitin (c) 2019
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Publish.ps1:
--------------------------------------------------------------------------------
1 | $items = ls .\bin\Release\*.nupkg
2 | $package = $items | Out-GridView -OutputMode Single
3 | if ($package -eq $null){
4 | throw "Nothing selected"
5 | }
6 | #nuget setApiKey -Source https://resharper-plugins.jetbrains.com
7 |
8 | nuget push "$package" -Source https://plugins.jetbrains.com/
9 | pause
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ReSharper ZenSharp plugin
2 | ==============
3 |
4 | A shortcuts language for defining [ReSharper](https://www.jetbrains.com/resharper/) live template items. You can
5 | specify your own live template scheme using flexible language.
6 |
7 | 
8 |
9 | 
10 |
11 | How do I get it?
12 | ---
13 | You can install directly into ReSharper via the Extension Manager in the
14 | ReSharper menu.
15 |
16 | Predefined templates
17 | ---
18 | ZenSharp shipped with a lot of standard templates.
19 |
20 | `$END$` means cursor position after expand template by pressing Tab.
21 |
22 | **Examples** in scope, where method definition is allowed:
23 |
24 |
25 | | shortcut | expand to | how to memo |
26 | |----------|--------------------------------------------------------|-----------------------------------------------------------------------------|
27 | | pps | `public string $name$ { get; private set; } $END$` | **p**ublic **p**roperty **s**tring |
28 | | ppsAge | `public string Age {get; private set;} $END$` | **p**ublic **p**roperty **s**tring Name |
29 | | pps+ | `public string $name$ { get; set; } $END$` | **p**ublic **p**roperty **s**tring more access! |
30 | | ppsA+p | `public string A {get; protected set;} $END$` | **p**ublic **p**roperty **s**tring more access!**p**rotected |
31 | | \_rs | `private readonly string $name$; $END$ ` | [**_** is private] **r**eadonly **s**tring |
32 | | pvm | `public virtual void $name$($END$) { } ` | **p**ublic **v**irtual **m**ethod |
33 | | pM\~s | `public static IEnumerable $name$($END$) { } ` | public [static **M**ethod] _returning_ [**\~** is IEnumerable] of **s**tring |
34 | | pamb | `public abstract bool $name$($END$) { } ` | **p**ublic **a**bstract **m**ethod **b**ool |
35 | | pmiaTest | `public int[] Test() { $END$ }` | **p**ublic **m**ethod _returning_ **i**nt **a**rray Name |
36 |
37 |
38 |
39 | **Examples** where type declaration is allowed:
40 |
41 | | shortcut | expand to | how to memo |
42 | |----------|------------------------------------------|---------------------------------|
43 | | pi | `public interface $name$ { $END$ }` | **p**ublic **i**nterface |
44 | | psc | `public sealed class $name$ { $END$ }` | **p**ublic **s**ealed **c**lass |
45 | | pc:t | `public class $name$ : $type$ { $END$ }` | **p**ublic **c**lass **:t**ype |
46 | | ie | `internal enum $name$ { $END$ }` | **i**nternal **e**num |
47 |
48 | **Hint**: you can always write variable name after shortcut. For example, you can type `ppsPropertyName` and
49 | by pressing tab it magically expand to `public string PropertyName {get; set; }`.
50 |
51 |
52 | #### Access
53 | | shortcut | expand to |
54 | |----------|-----------|
55 | | p | public |
56 | | _ | private |
57 | | i | internal |
58 | | P | protected |
59 |
60 |
61 | #### Types
62 | | shortcut | expand to | note |
63 | |----------|-----------|-------------------------------------------------|
64 | | t | $type$ | ask user for custom type after expand |
65 | | sa | string[] | any prim type end with `a` — array of this type |
66 | | b? | bool? | any prim type end with `?` — Nullable type |
67 |
68 |
69 | ##### Primitive types
70 | | shortcut | expand to |
71 | |----------|-----------|
72 | | s | string |
73 | | by | byte |
74 | | b | bool |
75 | | dt | DateTime |
76 | | d | double |
77 | | i | int |
78 | | ui | uint |
79 | | g | Guid |
80 | | dc | decimal |
81 | | b? | bool? |
82 |
83 |
84 | ##### Generic types
85 | | shortcut | expand to |
86 | |----------|-----------------|
87 | | l | IList |
88 | | ~ | IEnumerable |
89 | | sl | SortedList |
90 | | di | Dictionary |
91 |
92 | ##### NUnit attributes #####
93 | Some useful examples to help wring NUnit tests:
94 | [repo](https://github.com/ulex/ZenSharp/blob/master/ZenSharp.Integration/Templates.ltg) today)
95 |
96 |
97 | | shortcut | expand to |
98 | |------------------------|-------------------------------------------------------------|
99 | | **su**pmSetup | `[SetUp] public void Setup() { $END$ }` |
100 | | **tfsu**pmFixtureSetup | `[TestFixtureSetUp] public void FixtureSetup() { $END$ }` |
101 | | **tftd**FixtureDown | `[TestFixtureTearDown] public void FixtureDown() { $END$ }` |
102 | | **td**pmTearDown | `[TearDown] public void Test() { $END$ }` |
103 | | **tc**pmTest | `[TestCase] public void Test() { $END$ }` |
104 | | **t**pmTest | `[Test] public void Test() { $END$ }` |
105 |
106 | Rules
107 | ---
108 | Simplest rule for expand text `cw` into `System.Console.WriteLine($END$)`(this
109 | rule is ordinary ReSharper live template) will looks like `start ::=
110 | "cw"="System.Console.WriteLine($END$)"`
111 |
112 | More complex rule, a sort of predefined live template for define class in scope,
113 | where class declaration is allowed. In ordinary live templates, if you want to
114 | specify class access before executing live template, you must define
115 | independent live templates one for `"public class"`=`pc`, another for `"internal class"=ic`
116 | But class can be also be sealed. Or static. And same access modifier can be
117 | applied to interface and enum.
118 |
119 | In ZenSharp config you can simple define rules like formal grammar.
120 | For class declaration this definition will looks like:
121 |
122 | space ::= " "
123 | cursor ::= "$END$"
124 | identifier ::=
125 |
126 | access ::= (internal=i | public=p | private=_ | protected=P) space
127 | class ::= access ["sealed "=s] ("class"=c | "static class"=C) space body
128 | body ::= identifier "{" cursor "}"
129 |
130 | scope "InCSharpTypeAndNamespace"
131 | {
132 | start = class | interface
133 | }
134 |
135 | More complex example available in predefined templates file.
136 |
137 | How to compile
138 | ---
139 | ZenSharp written in C# and Nemerle programming language. You can install it from Nemerle website http://nemerle.org/Downloads .
140 | ZenSharp depend on nuget packages ReSharper.SDK and nunit.framwork. Use nuget package restore for them.
141 |
142 | After this, ZenSharp can be built either msbuild or Visual Studio.
143 |
144 | External links
145 | ---
146 | https://blog.jetbrains.com/dotnet/2015/12/22/end-of-year-round-up-of-resharper-10-extensions/
147 | https://garyng.github.io/gtil-gitbook/ReSharper/resharper-plugin-zensharp.html
148 |
149 |
150 |
163 |
--------------------------------------------------------------------------------
/ZenSharp.Core/GenerateTree.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 |
6 | using System;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Collections.Generic;
10 |
11 | namespace Github.Ulex.ZenSharp.Core
12 | {
13 | [Record]
14 | public class GenerateTree
15 | {
16 | public GlobalRules : list[Rule];
17 | public Scopes : list[TreePart.Scope];
18 |
19 | public GetScope(scopename : string) : TreePart.Scope
20 | {
21 | def scope = Scopes.Find(a => a.Name == scopename);
22 | if (!scope.IsSome)
23 | throw Exception($"scope with name $scopename does not exist")
24 | else
25 | scope.Value;
26 | }
27 |
28 | public IsScopeExist(scopename : string) : bool
29 | {
30 | def scope = Scopes.Find(a => a.Name == scopename);
31 | scope.IsSome;
32 | }
33 |
34 | public GetRule(rulename : string, scopeRules : list[Rule]) : Rule
35 | {
36 | def rule = scopeRules.Find(r => r.Name == rulename);
37 | if (rule.IsSome)
38 | rule.Value
39 | else
40 | throw Exception($"Non-terminal rule '$rulename' does not exist");
41 | }
42 |
43 | public GetStartRule(scope : TreePart.Scope) : Rule
44 | {
45 | def startRule = scope.Rules.Find(a => a.Name == "start");
46 | if (!startRule.IsSome)
47 | throw Exception($"Start rule for scope $(scope.Name) does not exist")
48 | else
49 | startRule.Value;
50 | }
51 |
52 | GetTemplatesRule(rule : Rule, scopeRules : list[Rule]): IEnumerable[list[LeafRule]]
53 | {
54 | foreach (crule in rule.Rules)
55 | {
56 | foreach (gen in GetTemplatesLr(crule.Rules, scopeRules)) yield gen;
57 | }
58 | }
59 |
60 | GetTemplatesLr(leafRules : list[LeafRule], scopeRules : list[Rule]) : IEnumerable[list[LeafRule]]
61 | {
62 | def (left, current, right) = leafRules.SplitFirst(lr => lr is LeafRule.NonTerminal);
63 | match (current) {
64 | | Some ( x is LeafRule.NonTerminal ) =>
65 | {
66 | def rule = GetRule(x.Value, scopeRules);
67 |
68 | // Expand first non-terminal rule
69 | foreach (expand in GetTemplatesRule(rule, scopeRules))
70 | // Expand tail rules
71 | foreach (rightExpand in GetTemplatesLr(right, scopeRules))
72 | yield left + expand + rightExpand;
73 | }
74 | | None => yield leafRules
75 | }
76 | }
77 |
78 | public ExtendWithAnotherTree(tree : GenerateTree, namePrefix : string) : GenerateTree
79 | {
80 | def prefix = namePrefix + ":";
81 |
82 | def patchLeafRule(leaf)
83 | {
84 | match (leaf){
85 | | x is LeafRule.NonTerminal => LeafRule.NonTerminal(prefix + x.Value);
86 | | x => x;
87 | }
88 | }
89 |
90 | def patchRule(rule) {
91 | rule.Patch(prefix + rule.Name, patchLeafRule);
92 | }
93 |
94 | def patchScope(scope){
95 | TreePart.Scope(scope.Rules.Select(patchRule).NToList(), scope.Name);
96 | }
97 |
98 | def newGlobalRules = tree.GlobalRules.Select(patchRule).NToList();
99 | def updatedScopes = tree.Scopes.Select(patchScope).NToList();
100 |
101 | GenerateTree(GlobalRules + newGlobalRules, Scopes + updatedScopes);
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/ZenSharp.Core/LiveTemplateMatcher.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 |
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace Github.Ulex.ZenSharp.Core
11 | {
12 | public class LiveTemplateMatcher
13 | {
14 | private _tree : GenerateTree;
15 |
16 | public this(tree : GenerateTree) {
17 | _tree = tree;
18 | }
19 |
20 | [Record]
21 | public class MatchResult {
22 | public Success : bool { get; private set; }
23 | public Tail : string { get; private set };
24 | public Rules : list[LeafRule] { get; private set; }
25 |
26 | public this(mr : bool) {
27 | Success = mr;
28 | }
29 |
30 | public Expand(prefix : string) : string {
31 | def builder = System.Text.StringBuilder();
32 | foreach (r in ReMatchLeafs(prefix)){
33 | _ = builder.Append(r.Expand)
34 | }
35 | builder.ToString();
36 | }
37 |
38 | public ReMatchLeafs(prefix : string) : IEnumerable[LeafRule.LeafMatchResult]{
39 | def loop(tail, input, acc){
40 | match (tail){
41 | | x :: xs => {def matchResult = x.Match(input); loop(xs, matchResult.Crop(input), matchResult :: acc); }
42 | | _ => acc
43 | }
44 | }
45 | loop(Rules, prefix, []).Reverse();
46 | }
47 | }
48 |
49 | public class MatchResultWithSuggestion : MatchResult {
50 | public Suggestion : MatchResult;
51 |
52 | public this(success : bool, tail : string, rules : list[LeafRule], suggestion : MatchResult)
53 | {
54 | base(success, tail, rules);
55 | // choose best fit
56 | if (suggestion == null || tail.Length < suggestion.Tail.Length){
57 | Suggestion = this;
58 | } else{
59 | Suggestion = suggestion;
60 | }
61 | }
62 |
63 | public this(mr : MatchResult, suggestion : MatchResult){
64 | this(mr.Success, mr.Tail, mr.Rules, suggestion);
65 | }
66 | }
67 |
68 | public Match (prefix : string, scopename : string) : MatchResultWithSuggestion
69 | {
70 | def scope = _tree.GetScope(scopename);
71 |
72 | // scope rules can override global rules
73 | def scopeRules = scope.Rules + _tree.GlobalRules;
74 |
75 | // circle reference fix
76 | mutable tryMatchRuleVar;
77 |
78 | def tryMatchLeafRule(rule : LeafRule, acc){
79 | match (rule){
80 | | x is LeafRule.NonTerminal => tryMatchRuleVar(_tree.GetRule(x.Value, scopeRules).Rules, acc);
81 | | x is LeafRule.InsideRule => tryMatchRuleVar(x.Rules, acc);
82 | | lr => {
83 | def leafMatch = lr.Match(acc.Tail);
84 | MatchResultWithSuggestion(leafMatch.Success, leafMatch.Crop(acc.Tail), rule :: acc.Rules, acc.Suggestion)
85 | }
86 | }
87 | }
88 |
89 | def tryMatchConcatRule (rules : list[LeafRule], acc){
90 | match (rules) {
91 | | x :: xs => {
92 | def r = tryMatchLeafRule(x, acc);
93 | if (!r.Success)
94 | r
95 | else
96 | tryMatchConcatRule(xs, r);
97 | }
98 | | _ => acc;
99 | }
100 | }
101 |
102 | def tryMatchRule (rules : list[ConcatRule], acc){
103 | match (rules) {
104 | | x :: xs =>
105 | {
106 | def r = tryMatchConcatRule(x.Rules, acc);
107 | if (r.Success)
108 | r
109 | else
110 | tryMatchRule(xs, MatchResultWithSuggestion(acc, r.Suggestion));
111 | };
112 | | _ => MatchResultWithSuggestion(false, acc.Tail, acc.Rules, acc.Suggestion);
113 | }
114 | }
115 | tryMatchRuleVar = tryMatchRule;
116 |
117 | def iSuggest = MatchResult(false, prefix, []);
118 | def result = tryMatchRule(_tree.GetStartRule(scope).Rules, MatchResultWithSuggestion(true, prefix, [], iSuggest));
119 |
120 | def suggestion = MatchResult(result.Suggestion.Success, result.Suggestion.Tail, result.Suggestion.Rules.Reverse());
121 | MatchResultWithSuggestion(result.Success, result.Tail, result.Rules.Reverse(), suggestion);
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Parser/ConcatRule.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 | using Nemerle.Peg;
6 |
7 | using System;
8 | using System.Console;
9 | using System.Collections.Generic;
10 |
11 | namespace Github.Ulex.ZenSharp.Core
12 | {
13 | [Record]
14 | public class ConcatRule
15 | {
16 | public Rules : list[LeafRule];
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Parser/ErrorContextLocator.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 |
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace Github.Ulex.ZenSharp.Core
11 | {
12 | public module ErrorContextLocator
13 | {
14 | public GetContext(input : string, index : int) : string {
15 | if (index >= input.Length){
16 | "At the end of file";
17 | } else {
18 | def nextInd = input.IndexOf('\n', index);
19 | def prevInd = input.LastIndexOf('\n', index);
20 | def prev = if (prevInd == -1) 0 else prevInd;
21 | def length = if (nextInd == -1) input.Length - prev else nextInd - prev;
22 |
23 | def lineNu = input.Substring(0, index).Count(ch => ch == '\n') + 1;
24 |
25 | string.Format("Error at line {0}, column {1}: cant parse {2}{3} ",
26 | lineNu,
27 | index - prev,
28 | Environment.NewLine,
29 | input.Substring(prev, length));
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Parser/LeafRule.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 | using Nemerle.Peg;
6 |
7 | using System;
8 | using System.Linq;
9 | using System.Console;
10 | using System.Collections.Generic;
11 |
12 |
13 | namespace Github.Ulex.ZenSharp.Core
14 | {
15 | public variant LeafRule
16 | {
17 | | String {
18 | Value : string;
19 | public override ToString() : string { $"String<$Value>"; }
20 | public override Match(_ : string) : LeafMatchResult {
21 | LeafMatchResult(true, "", Value, this)
22 | }
23 | }
24 | | NonTerminal {
25 | Value : string;
26 | public override ToString() : string { $"NonTerminal<$Value>"; }
27 | public override Match(_ : string) : LeafMatchResult {
28 | throw NotImplementedException();
29 | }
30 | }
31 | | InsideRule {
32 | public override ToString() : string { "InsideRule<>"; }
33 | public Rules : list[ConcatRule];
34 | public override Match(_ : string) : LeafMatchResult {
35 | throw NotImplementedException();
36 | }
37 | }
38 | | ExpandRule {
39 | Short : string;
40 | Expand : string;
41 | public override ToString() : string { $"ExpandRule<$Short,$Expand>"; }
42 | public override Match(input : string) : LeafMatchResult {
43 | if (input.StartsWith(Short) && input.Length > 0)
44 | LeafMatchResult(true, Short, Expand, this);
45 | else
46 | LeafMatchResult(false);
47 | }
48 | }
49 | | Substitution {
50 | Name : string;
51 | Params: list[(string * string)];
52 |
53 | public Item[s : string] : string{
54 | get{
55 | def v = Params.Find(k => k[0] == s);
56 | if (v.IsSome) v.Value[1] else null;
57 | }
58 | }
59 | private Prop[T](prop : string, default : T) : T {
60 | def val = this[prop];
61 | if (val != null) Convert.ChangeType(val, typeof(T), Globalization.CultureInfo.InvariantCulture) :> T;
62 | else default;
63 | }
64 |
65 | public Default : string {
66 | get{
67 | Prop("default", null);
68 | }
69 | }
70 |
71 | public Expand : string {
72 | get{
73 | Prop("expand", null);
74 | }
75 | }
76 |
77 | public Short : string {
78 | get{
79 | Prop("short", null);
80 | }
81 | }
82 |
83 | public CanBeNull : bool{
84 | get{
85 | !String.IsNullOrEmpty(Default);
86 | }
87 | }
88 |
89 | public override Match (input : string) : LeafMatchResult {
90 | def loop(pos){
91 | if (pos >= input.Length || !Identifier.IsIdentifier(input[pos]))
92 | pos;
93 | else
94 | loop(pos + 1);
95 | }
96 |
97 | if (Short != null && Expand != null){
98 | def em = LeafRule.ExpandRule(Short,Expand).Match(input);
99 | LeafMatchResult(em.Success, em.Short, em.Expand, this);
100 | }
101 | else
102 | {
103 | def matchedCount = loop(0);
104 | if (matchedCount != 0){
105 | def matchString = input.Substring(0, matchedCount);
106 | LeafMatchResult(true, matchString, matchString, this);
107 | }
108 | else if (CanBeNull)
109 | LeafMatchResult(true, "", Default, this);
110 | else
111 | LeafMatchResult(false);
112 | }
113 | }
114 |
115 | public override ToString() : string {
116 | def kvpFormat(kvp: string * string) { string.Format("{0}={1}", kvp[0], kvp[1]); }
117 | string.Format("Substitution<{0}:{1}>", Name, string.Join(", ", Params.Map(kvpFormat)));
118 | }
119 | }
120 |
121 | [Record]
122 | public class LeafMatchResult {
123 | public Success : bool;
124 | public Short : string;
125 | public Expand : string;
126 | public This : LeafRule;
127 |
128 | public this(success : bool){
129 | Success = success;
130 | }
131 |
132 | public Crop(input : string) : string {
133 | if (String.IsNullOrEmpty(input) || String.IsNullOrEmpty(Short))
134 | input;
135 | else
136 | input.Remove(0, Short.Length);
137 | }
138 | }
139 |
140 | public abstract Match (input : string) : LeafMatchResult;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Parser/LtgParser.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 | using Nemerle.Peg;
6 |
7 | using System;
8 | using System.Linq;
9 | using System.Console;
10 | using System.Collections.Generic;
11 |
12 | namespace Github.Ulex.ZenSharp.Core
13 | {
14 | [PegGrammar(Options = EmitDebugSources, start,
15 | grammar
16 | {
17 | start : GenerateTree = generate+;
18 | generate: TreePart = sn (rules / scope / comment);
19 | // Todo: comment to lexer parsing level
20 | comment : TreePart = s "//" (!newLine [Any])* sn;
21 |
22 | newLineCharacter : void = '\n' / '\r' / '\u2028' / '\u2029';
23 | newLineWindows : void = "\r\n";
24 | newLine : void = newLineWindows / newLineCharacter;
25 | whitespace : void = [Zs] / '\t' / '\v' / '\f';
26 | space : void = whitespace / newLine;
27 | s : void = whitespace*;
28 | sn : void = space*;
29 | vmark : void = '|';
30 | describeMark : void = "::=";
31 |
32 | stringChar : string = !"\"" [Any];
33 | quoteEscapeSequence : string = "\"\"";
34 | str : string = (quoteEscapeSequence / stringChar)*;
35 | stringDecl : string = '@'? '"' (str) '"';
36 | identifier : string = ([Lu, Ll, Lt, Lm, Lo, Nl, Nd] / '_')+;
37 | stridentifier : string = stringDecl / identifier;
38 |
39 | scope : TreePart = "scope" s stringDecl s '{' sn (rules / comment)* '}' sn;
40 |
41 | rules : TreePart = rule sn (rule sn)*;
42 | expandRule : LeafRule = terminal / nonterminal / maybeNonterminal / maybeBrackets / brackets;
43 | maybeBrackets : LeafRule = "(" s ruleBody s ")?";
44 | brackets : LeafRule = "(" s ruleBody s ")";
45 | concatRule : ConcatRule = expandRule (s expandRule)*;
46 | ruleBody : list[ConcatRule] = concatRule (sn vmark sn concatRule)*;
47 | rule : Rule = identifier s describeMark sn vmark? s ruleBody;
48 | leafShortCut : LeafRule = stridentifier s '=' s stridentifier;
49 | terminalString : LeafRule = stringDecl;
50 | terminal : LeafRule = leafShortCut / substituion / terminalString;
51 | substituion : LeafRule = "<" s (identifier) s (substituionPar s)* ">";
52 | substituionPar : string * string = identifier s "=" s stringDecl;
53 |
54 | nonterminal : LeafRule = identifier;
55 | maybeNonterminal : LeafRule = identifier "?";
56 | }
57 | )]
58 | public class LtgParser
59 | {
60 | comment(_ : NToken, _ : NToken) : TreePart {
61 | null;
62 | }
63 |
64 | substituion(_ : NToken, name : string, options : List[(string * string)], _ : NToken) : LeafRule
65 | {
66 | LeafRule.Substitution(name, options.AsList());
67 | }
68 |
69 | substituionPar(k : string, _ : NToken, v : string) : (string * string)
70 | {
71 | (k,v);
72 | }
73 |
74 | scope(_ : NToken, name : string, _ : NToken, rules : List[TreePart], _ : NToken) : TreePart{
75 | def loop(rules : list[TreePart], acc : list[Rule]) {
76 | match (rules){
77 | | null :: xs => loop(xs, acc)
78 | | x :: xs => acc + loop(xs, acc + (x :> TreePart.RuleList).Rules)
79 | | _ => acc
80 | }
81 | }
82 | TreePart.Scope(loop(NList.AsList(rules), []), name);
83 | }
84 |
85 | rules(first : Rule, tail : List[Rule]) : TreePart{
86 | TreePart.RuleList(first :: tail.AsList());
87 | }
88 |
89 | concatRule(first : LeafRule, tail : List[LeafRule]) : ConcatRule{
90 | ConcatRule(first :: tail.AsList());
91 | }
92 |
93 | ruleBody (crule : ConcatRule, tail : List[ConcatRule]): list[ConcatRule]{
94 | crule :: tail.AsList();
95 | }
96 | rule (id : string, rules : list[ConcatRule]): Rule{
97 | Rule(id, rules)
98 | }
99 | leafShortCut (expand : string, _ : NToken, sho : string) : LeafRule{
100 | LeafRule.ExpandRule(sho, expand);
101 | }
102 |
103 | terminalString (decl : string) : LeafRule{
104 | LeafRule.String(decl);
105 | }
106 |
107 | maybeNonterminal (id : string, _ : NToken) : LeafRule{
108 | LeafRule.InsideRule([ConcatRule([LeafRule.NonTerminal(id)]), ConcatRule([])])
109 | }
110 |
111 | nonterminal (id : string) : LeafRule{
112 | LeafRule.NonTerminal(id)
113 | }
114 |
115 | brackets(_ : NToken, ruleBody : list[ConcatRule], _ : NToken) : LeafRule{
116 | LeafRule.InsideRule(ruleBody);
117 | }
118 |
119 | maybeBrackets(_ : NToken, ruleBody : list[ConcatRule], _ : NToken) : LeafRule{
120 | def parseablePart = ConcatRule([LeafRule.InsideRule(ruleBody)]);
121 | def emptyAlternative = ConcatRule([]);
122 | LeafRule.InsideRule([parseablePart, emptyAlternative]);
123 | }
124 |
125 | identifier (sequence : NToken) : string {
126 | GetText(sequence);
127 | }
128 | private quoteEscapeSequence(_ : NToken) : string{
129 | "\"";
130 | }
131 |
132 | private stringChar (text : NToken) : string{
133 | GetText(text)
134 | }
135 |
136 | private str(parts : List[string]) : string{
137 | System.String.Concat(parts);
138 | }
139 |
140 | stringDecl(_ : NToken, _ : NToken, inside : string, _ : NToken) : string{
141 | inside;
142 | }
143 |
144 | start(declaration : List[TreePart]) : GenerateTree{
145 | // todo: use native nemerle list
146 | def globalRules = List();
147 | def scopes = List();
148 | foreach (treePart in declaration)
149 | {
150 | match (treePart){
151 | | scope is TreePart.Scope => scopes.Add(scope)
152 | | rules is TreePart.RuleList => globalRules.Add(rules)
153 | | _ => ()
154 | }
155 | }
156 | GenerateTree($[y | x in globalRules, y in x.Rules], scopes.AsList());
157 | }
158 |
159 | public ParseAll(input : string) : GenerateTree {
160 | def d = LtgParser();
161 | def (count, parseresult) = d.TryParse(input);
162 |
163 | if(count == input.Length && parseresult != null)
164 | {
165 | parseresult;
166 | }
167 | else
168 | {
169 | def context = ErrorContextLocator.GetContext(input, count + 1);
170 | throw ParsingException($"Parsing error. Parsed part is <$context>", input, count);
171 | }
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Parser/ParsingException.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 |
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace Github.Ulex.ZenSharp.Core
11 | {
12 | public class ParsingException : Exception
13 | {
14 | public Input : string { get; set; };
15 | public ParsedCount: int { get; set; };
16 |
17 | public this(message : string, input : string, parsedCount : int){
18 | base(message);
19 | Input = input;
20 | ParsedCount = parsedCount;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Parser/Rule.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 | using Nemerle.Peg;
6 |
7 | using System;
8 | using System.Console;
9 | using System.Collections.Generic;
10 |
11 | namespace Github.Ulex.ZenSharp.Core
12 | {
13 | [Record]
14 | public class Rule
15 | {
16 | public Name : string;
17 | public Rules : list[ConcatRule];
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Parser/TreePart.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 | using Nemerle.Peg;
6 |
7 | using System;
8 | using System.Console;
9 | using System.Collections.Generic;
10 |
11 | namespace Github.Ulex.ZenSharp.Core
12 | {
13 | [Record]
14 | public variant TreePart
15 | {
16 | | RuleList
17 | | Scope {
18 | Name : string;
19 | }
20 | public Rules : list[Rule];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Properties/AssemblyInfo.n:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | [assembly: Nemerle.Macro.Resource(@"Properties\Resources.resx")]
6 | [assembly: Nemerle.Macro.Settings(@"Properties\Settings.settings")]
7 |
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 | [assembly: AssemblyTitle("ZenSharp.Core")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("Alexander Ulitin")]
15 | [assembly: AssemblyProduct("ZenSharp.Core")]
16 | [assembly: AssemblyCopyright("")]
17 | [assembly: AssemblyTrademark("")]
18 | [assembly: AssemblyCulture("")]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 | [assembly: Guid("efa574e2-de9c-4017-bb5c-8fc4cd8d5e80")]
27 |
28 | // Version information for an assembly consists of the following four values:
29 | //
30 | // Major Version
31 | // Minor Version
32 | // Build Number
33 | // Revision
34 | //
35 | [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyFileVersion("1.0.*")]
37 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Utils/Identifier.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 | using Nemerle.Peg;
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Linq;
10 |
11 | namespace Github.Ulex.ZenSharp.Core
12 | {
13 | module Identifier
14 | {
15 | public IsIdentifier(this rs : char) : bool {
16 | // ToDo: use range clasess from c# lexer specification
17 | Char.IsLetterOrDigit(rs) || rs == '_';
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Utils/ListExtensions.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 |
6 | namespace Github.Ulex.ZenSharp.Core
7 | {
8 | module ListExtensions
9 | {
10 | public SplitFirst[T](this l : list[T], pred : T -> bool) : list[T] * option[T] * list[T]
11 | {
12 | def loop(acc : list[T], ls : list[T], predicate : T->bool){
13 | match (ls){
14 | | x :: xs => if (predicate(x)) (acc.Rev(), Some(x), xs) else loop(x::acc, xs, predicate)
15 | | [] => (acc.Rev(), None(), [])
16 | }
17 | }
18 | loop ([], l, pred)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Utils/MultiDict.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 |
6 | using System;
7 | using SCG = System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace Github.Ulex.ZenSharp.Core
11 | {
12 | public class MultiDict[K,V] : Hashtable[K, list[V]]
13 | {
14 | public AddMulti(key : K, val : V) : void
15 | {
16 | match (Get(key)){
17 | | None => this.Set(key, [val])
18 | | Some (x) => this.Set(key, val :: x)
19 | }
20 | }
21 |
22 | public Longer2() : SCG.IEnumerable[K * list[V]]
23 | {
24 | foreach (kvp in this)
25 | {
26 | match (kvp.Value){
27 | | _ :: _ :: _ => yield (kvp.Key, kvp.Value)
28 | | _ => ()
29 | }
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ZenSharp.Core/Utils/RuleFactory.n:
--------------------------------------------------------------------------------
1 | using Nemerle;
2 | using Nemerle.Collections;
3 | using Nemerle.Text;
4 | using Nemerle.Utility;
5 |
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace Github.Ulex.ZenSharp.Core
11 | {
12 | module RuleFactory
13 | {
14 | public Patch(this rule : Rule, newname : string, patch : Func[LeafRule, LeafRule]): Rule
15 | {
16 | def patchConcat(crule)
17 | {
18 | ConcatRule(crule.Rules.Select(patch).NToList());
19 | }
20 |
21 | Rule(newname, rule.Rules.Select(patchConcat).NToList())
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/Data/jack.ltg:
--------------------------------------------------------------------------------
1 | // This is the house that Jack built.
2 | // This is the cheese that lay in the house that Jack built.
3 | // This is the rat that ate the cheese
4 | // That lay in the house that Jack built.
5 |
6 | tjb ::= "that Jack built"=tjb
7 | thisis ::= "This is the"=tit
8 | s ::= " "
9 | sentence ::= $sencence par="value" par2="sample" $
10 | sep ::= ", "=","
11 |
12 | scope "house" {
13 | base ::= thisis s sentence
14 | start ::= base | base sep tjb
15 | // Test: tithouse -> This is the house
16 | // Test: tithouse,tjb -> This is the house
17 | }
18 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/Doc/RailroadGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.CodeDom.Compiler;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 |
9 | using Github.Ulex.ZenSharp.Core;
10 |
11 | using Nemerle.Core;
12 |
13 | using NUnit.Framework;
14 |
15 | namespace ZenSharp.Core.Tests.Doc
16 | {
17 | [TestFixture]
18 | [Explicit]
19 | internal sealed class RailroadGenerator
20 | {
21 | private GenerateTree _tree;
22 |
23 | private IEnumerable _globalRules;
24 |
25 | private readonly HashSet _alwaysExpandRules = new HashSet()
26 | {
27 | "space",
28 | "methodBody",
29 | "methodArgs",
30 | "access",
31 | "SCG",
32 | //"type",
33 | "primType",
34 | "generic",
35 | "suggType",
36 | "propertyBody",
37 | "cursor",
38 | "classBody"
39 | };
40 |
41 | private readonly HashSet _ignoredStrings = new HashSet() { " " };
42 |
43 | private const string TemplatesRelativePath = SolutionDir + @"ZenSharp.Integration\Templates.ltg";
44 |
45 | private const string SolutionDir = @"..\..\";
46 |
47 | public const string OutFile = DocDir + "out.html";
48 |
49 | private const string DocDir = SolutionDir + "doc\\";
50 |
51 | [OneTimeSetUp]
52 | public void FixtureSetup()
53 | {
54 | _tree = new LtgParser().Parse(File.ReadAllText(TemplatesRelativePath)).Value;
55 | }
56 |
57 | [Test]
58 | public void DumpNodes()
59 | {
60 | using (var dump = new StreamWriter(OutFile))
61 | {
62 | dump.WriteLine(@"");
63 | dump.WriteLine(@"");
64 | dump.WriteLine(@"");
65 | dump.WriteLine(@"");
66 |
67 | _globalRules = _tree.GlobalRules;
68 |
69 | foreach (var scope in _tree.Scopes)
70 | {
71 | _globalRules = scope.Rules.Concat(_tree.GlobalRules);
72 |
73 | dump.WriteLine("{0}
", scope.Name);
74 | foreach (var rule in scope.Rules.Where(f => !_alwaysExpandRules.Contains(f.Name)))
75 | {
76 | WriteH2Script(dump, rule.Name, DumpConcatRules(rule.Rules));
77 | }
78 |
79 | }
80 |
81 | dump.WriteLine("Global
");
82 | foreach (var rule in _globalRules)
83 | {
84 | WriteH2Script(dump, rule.Name, DumpConcatRules(rule.Rules));
85 | }
86 |
87 | dump.WriteLine(@"");
88 | }
89 | }
90 |
91 | private void WriteH2Script(StreamWriter dump, string name, string script)
92 | {
93 | dump.WriteLine("{0}
", name);
94 | dump.WriteLine("");
97 | }
98 |
99 | public string DumpConcatRules(IEnumerable concatRules)
100 | {
101 | var list = new List();
102 | foreach (var concatRule in concatRules)
103 | {
104 | list.Add(DumpConcatRule(concatRule));
105 | }
106 | return string.Format("Choice(0, {0})", string.Join(",", list));
107 | }
108 |
109 | private string DumpConcatRule(ConcatRule concatRule)
110 | {
111 | var listlr = new List();
112 | foreach (var leafRule in concatRule.Rules)
113 | {
114 | var item = Dump(leafRule as LeafRule.String) ??
115 | Dump(leafRule as LeafRule.Substitution) ??
116 | Dump(leafRule as LeafRule.ExpandRule) ??
117 | Dump(leafRule as LeafRule.InsideRule) ??
118 | Dump(leafRule as LeafRule.NonTerminal);
119 | if (item != null) listlr.Add(item);
120 | }
121 | return string.Format("Sequence({0})", string.Join(",", listlr));
122 | }
123 |
124 | private string Dump(LeafRule.InsideRule leafRule)
125 | {
126 | if (leafRule == null) return null;
127 | return DumpConcatRules(leafRule.Rules.ToArray());
128 | // return string.Format("NonTerminal('{0}')", leafRule.)
129 | }
130 |
131 | private string Dump(LeafRule.NonTerminal leafRule)
132 | {
133 | if (leafRule == null) return null;
134 | if (_alwaysExpandRules.Contains(leafRule.Value))
135 | {
136 | return DumpConcatRules(_globalRules.First(r => r.Name == leafRule.Value).Rules);
137 | }
138 | return string.Format("NonTerminal('{0}')", leafRule.Value);
139 | }
140 |
141 | private string Dump(LeafRule.ExpandRule leafRule)
142 | {
143 | if (leafRule == null) return null;
144 | return string.Format("NonTerminal('{0} = {1}')", leafRule.Expand, leafRule.Short);
145 | }
146 |
147 | private string Dump(LeafRule.String leafRule)
148 | {
149 | if (leafRule == null) return null;
150 |
151 | if (_ignoredStrings.Contains(leafRule.Value))
152 | {
153 | return null;
154 | }
155 |
156 | var escapeNsNames = Regex.Replace(leafRule.Value, "[\\w.]+\\.", String.Empty);
157 | return string.Format("Terminal('{0}')", escapeNsNames);
158 | }
159 |
160 | private string Dump(LeafRule.Substitution leafRule)
161 | {
162 | if (leafRule == null) return null;
163 | return string.Format("NonTerminal('{0}{1}')", leafRule.Expand, leafRule.Short);
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/ExpandTestGenerator.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 | using System;
11 | using Github.Ulex.ZenSharp.Core;
12 | using NUnit.Framework;
13 |
14 | namespace ZenSharp.Core.Tests
15 | {
16 | [TestFixture]
17 | public class TemplatesTests
18 | {
19 | #region Input of ltg
20 | public string _content = @"// C# templates
21 | // Sample file
22 | space ::= "" ""
23 | cursor ::= ""$END$""
24 | cursorb ::= ""("" cursor "")""
25 | // Resharper macros:
26 | identifier ::=
27 | identifier2 ::=
28 | //
29 | // Types:
30 | //
31 | suggType ::=
32 |
33 | // Primive types:
34 | maybeType ::= type | ""void""
35 | type ::= generic | primType (""?""=""?"")? (""[]""=a)? | suggType
36 | primType ::= string=s | byte=by | bool=b | ""System.DateTime""=dt | decimal=dc | double=d | int=i | uint=ui | ""System.Guid""=g | ""System.Uri""=u | ""System.Xml.Linq.XElement""=x |
37 | object=o
38 | taskType ::= ""System.Threading.Tasks.Task""
39 |
40 | // Complex types:
41 | generic1 ::= (SCG ""."" (""IList""=l | ""IEnumerable""=""~"")) ""<"" type "">""
42 | generic2 ::= (SCG ""."" (""SortedList""=sl | ""IDictionary""=di)) ""<"" type "", "" type "">""
43 | SCG ::= ""System.Collections.Generic""
44 | generic ::= generic1 | generic2
45 |
46 |
47 | access ::= (internal=i | public=p | private=_ | protected=P) space
48 |
49 | // Auto properties:
50 | property ::= access (""abstract ""=ap | ""static ""=P | ""virtual ""=vp | """"=p) type space identifier propertyBody cursor
51 | propertyBody ::= ""{ get;"" propertySetAccessor "" set; }""
52 | propertySetAccessor ::= ""protected ""=""+p"" | """"=""+"" | ""private ""
53 |
54 | // Methods:
55 | methodAttributes ::=
56 | | ""[NUnit.Framework.SetUpAttribute]""=su
57 | | ""[NUnit.Framework.TestFixtureSetUpAttribute]""=tfsu
58 | | ""[NUnit.Framework.TestFixtureTearDownAttribute]""=tftd
59 | | ""[NUnit.Framework.TearDownAttribute]""=td
60 | | ""[NUnit.Framework.TestCaseAttribute]""=tc
61 | | ""[NUnit.Framework.TestAttribute]""=t
62 | method_async ::= (methodAttributes)? access ""async"" space (""virtual ""=vm | ""abstract ""=am | ""static ""=M | """"=m) (taskType ""<""=T type "">"" | taskType """"=T) space identifier methodArgs methodBody
63 | method_generic ::= (methodAttributes)? access (""virtual ""=vm | ""abstract ""=am | ""static ""=M | """"=m) (type | ""void"") space identifier methodArgs methodBody
64 | method ::= method_async | method_generic
65 | methodBody ::= "" { "" cursor "" }""
66 | methodArgs ::= ""("" ((""""="","" | """"=""("") arg)? "")""
67 | arg ::= primType "" "" identifier2
68 |
69 | // Consts:
70 | const ::= access ""const ""=c primType space identifier ""= """""" identifier """""";""
71 |
72 | // Fields:
73 | field ::= access (""readonly ""=r)? type space identifier (""=""=""="" identifier2 "";"" | "";"")
74 |
75 | // Classes:
76 | classAtributes ::= (""[NUnit.Framework.TestFixtureAttribute]"" = tf)?
77 | class ::= classAtributes access (""sealed ""=s)? (""class""=c | ""static class""=C) space classBody
78 | classBody ::= identifier ("" : ""="":"" type)? ""{"" cursor ""}""
79 |
80 | //Enums:
81 | enum ::= access space ""enum""=e space identifier ""{"" cursor ""}""
82 |
83 | scope ""InCSharpClass"" {
84 | start ::= method | property | field | const | other
85 |
86 | other ::=
87 | | class
88 | | """"=dbset ""public DBSet<"" identifier "" > "" identifier ""s {get; set; }""
89 | }
90 |
91 | scope ""InCSharpTypeAndNamespace"" {
92 | start ::=
93 | | class
94 | | interface
95 | | enum
96 |
97 | interface ::= access ""interface""=i space classBody
98 | }
99 |
100 | scope ""InCSharpInterface"" {
101 | start ::=
102 | | type space identifier propertyBody cursor
103 | | method
104 | | property
105 |
106 | propertyBody ::= ""{ get; }"" | ""{ get; set; }""=""+""
107 | access ::= """"
108 | methodBody ::= "";""
109 | }
110 |
111 | scope ""InCSharpStruct"" {
112 | // start ::= """"
113 | }
114 |
115 | scope ""InCSharpStatement"" {
116 | start ::=
117 | | ""if (""=ifr identifier "" == null) return;""
118 | | ""Log.""=l (Fatal=f | Info=i | Error=e | Trace=t | Debug=d) ""("""""" cursor """""");""
119 | }
120 | ";
121 | #endregion Input of ltg
122 | private GenerateTree _tree;
123 | private LiveTemplateMatcher _ltm;
124 | [OneTimeSetUp]
125 | public void LoadTree()
126 | {
127 | _tree = new LtgParser().ParseAll(_content);
128 | _ltm = new LiveTemplateMatcher(_tree);
129 | }
130 |
131 | }
132 | [TestFixture]
133 | public class jackTests
134 | {
135 | #region Input of ltg
136 | public string _content = @"// This is the house that Jack built.
137 | // This is the cheese that lay in the house that Jack built.
138 | // This is the rat that ate the cheese
139 | // That lay in the house that Jack built.
140 |
141 | tjb ::= ""that Jack built""=tjb
142 | thisis ::= ""This is the""=tit
143 | s ::= "" ""
144 | sentence ::= $sencence par=""value"" par2=""sample"" $
145 | sep ::= "", ""="",""
146 |
147 | scope ""house"" {
148 | base ::= thisis s sentence
149 | start ::= base | base sep tjb
150 | // Test: tithouse -> This is the house
151 | // Test: tithouse,tjb -> This is the house
152 | }
153 | ";
154 | #endregion Input of ltg
155 | private GenerateTree _tree;
156 | private LiveTemplateMatcher _ltm;
157 | [OneTimeSetUp]
158 | public void LoadTree()
159 | {
160 | _tree = new LtgParser().ParseAll(_content);
161 | _ltm = new LiveTemplateMatcher(_tree);
162 | }
163 |
164 |
165 | [Test]
166 | public void Testtithouse_Thisisthehouse()
167 | {
168 | string input = @"tithouse";
169 | var m = _ltm.Match(input, @"house");
170 | var expand = m.Expand(input);
171 | Assert.IsTrue(m.Success);
172 | Assert.AreEqual(string.Empty, m.Tail, "Tail is not empty");
173 | Assert.AreEqual(@"This is the house", expand, "Expand diffs");
174 | }
175 |
176 | [Test]
177 | public void Testtithousetjb_Thisisthehouse()
178 | {
179 | string input = @"tithouse,tjb";
180 | var m = _ltm.Match(input, @"house");
181 | var expand = m.Expand(input);
182 | Assert.IsTrue(m.Success);
183 | Assert.AreEqual(string.Empty, m.Tail, "Tail is not empty");
184 | Assert.AreEqual(@"This is the house", expand, "Expand diffs");
185 | }
186 | }
187 | }
188 |
189 |
190 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/ExpandTestGenerator.tt:
--------------------------------------------------------------------------------
1 | <#@ template debug="false" hostspecific="true" language="C#" #>
2 | <#@ assembly name="System.Core" #>
3 | <#@ import namespace="System.IO" #>
4 | <#@ import namespace="System.Linq" #>
5 | <#@ import namespace="System.Text" #>
6 | <#@ import namespace="System.Collections.Generic" #>
7 | <#@ import namespace="System.Text.RegularExpressions" #>
8 | <#@ output extension=".cs" #>
9 | //------------------------------------------------------------------------------
10 | //
11 | // This code was generated by a tool.
12 | // Runtime Version:<#= System.Environment.Version #>
13 | //
14 | // Changes to this file may cause incorrect behavior and will be lost if
15 | // the code is regenerated.
16 | //
17 | //------------------------------------------------------------------------------
18 | using System;
19 | using Github.Ulex.ZenSharp.Core;
20 | using NUnit.Framework;
21 |
22 | namespace ZenSharp.Core.Tests
23 | {
24 | <#
25 | string folderTest = Host.ResolvePath("Data");
26 | string folder = Host.ResolvePath("../../ZenSharp.Integration");
27 | var ltgFiles = Directory.GetFiles(folder, "*.ltg").Concat(Directory.GetFiles(folderTest)).Select(LtgFileInfo.FromFile);
28 | foreach (var file in ltgFiles) { #>
29 | [TestFixture]
30 | public class <#= file.FileName #>Tests
31 | {
32 | #region Input of ltg
33 | public string _content = <#= file.ContentString #>;
34 | #endregion Input of ltg
35 | private GenerateTree _tree;
36 | private LiveTemplateMatcher _ltm;
37 | [TestFixtureSetUp]
38 | public void LoadTree()
39 | {
40 | _tree = new LtgParser().ParseAll(_content);
41 | _ltm = new LiveTemplateMatcher(_tree);
42 | }
43 | <# foreach (var test in file.Tests) {#>
44 |
45 |
46 | [Test]
47 | public void Test<#= test.TestName #>()
48 | {
49 | string input = <#= test.Short #>;
50 | var m = _ltm.Match(input, <#= test.Scope #>);
51 | var expand = m.Expand(input);
52 | Assert.IsTrue(m.Success);
53 | Assert.AreEqual(string.Empty, m.Tail, "Tail is not empty");
54 | Assert.AreEqual(<#= test.Expand #>, expand, "Expand diffs");
55 | }<#}#>
56 |
57 | }
58 | <#} // end file foreach
59 | #>
60 | }
61 |
62 |
63 | <#+
64 |
65 | public sealed class LtgFileInfo
66 | {
67 | public string Path { get; private set; }
68 | public string FileName { get {return System.IO.Path.GetFileNameWithoutExtension(Path);} }
69 | public string ContentString { get; private set; }
70 | public IEnumerable Tests{get; private set;}
71 |
72 | public static LtgFileInfo FromFile(string path)
73 | {
74 | var content = File.ReadAllText(path);
75 | var tests = new List();
76 | var lines = content.Split(new []{Environment.NewLine}, StringSplitOptions.None);
77 |
78 | string curscope = "";
79 | foreach (var line in lines) {
80 | var scopeMatch = Regex.Match(line, "scope \"([^\"]*)\"");
81 | if (scopeMatch.Success) curscope = scopeMatch.Groups[1].Value;
82 |
83 | var match = Regex.Match(line, "// ?Test: ?([^-]*)->(.*)$");
84 | if (match.Success)
85 | {
86 | tests.Add(new TestInfo {
87 | Short = ToDeclStr(match.Groups[1].Value.Trim()),
88 | Expand = ToDeclStr(match.Groups[2].Value.Trim()),
89 | Scope = ToDeclStr(curscope)
90 | });
91 | }
92 | }
93 |
94 | return new LtgFileInfo()
95 | {
96 | Path = path,
97 | Tests = tests,
98 | ContentString = ToDeclStr(content)
99 | };
100 | }
101 | public static string ToDeclStr(string input)
102 | {
103 | return "@\"" + input.Replace("\"", "\"\"") + "\"";
104 | }
105 |
106 | public class TestInfo
107 | {
108 | public string Scope { get; set; }
109 | public string Short { get; set; }
110 | public string Expand { get; set; }
111 | public string TestName { get { return new string((Short + "_" + Expand).Where(ch => Char.IsLetter(ch) || ch == '-' || ch == '_').ToArray()); } }
112 | }
113 | }
114 | #>
115 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/GetContextTests.cs:
--------------------------------------------------------------------------------
1 | using System;
using Github.Ulex.ZenSharp.Core;
using NUnit.Framework;
namespace ZenSharp.Core.Tests
{
[TestFixture]
internal sealed class GetContextTests
{
string _testFile = new TemplatesTests()._content;
[Test]
public void TestGetContextForAnyPosition()
{
for (int i = 0; i < _testFile.Length + 4; i++)
{
Console.WriteLine(ErrorContextLocator.GetContext(_testFile, i));
}
}
}
}
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/LeafRulesMatchTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using NUnit.Framework;
5 | using Github.Ulex.ZenSharp.Core;
6 | using N = Nemerle.Builtins;
7 |
8 | using Nemerle.Collections;
9 |
10 | namespace ZenSharp.Core.Tests
11 | {
12 | internal sealed class LeafRulesMatchTest
13 | {
14 | [Test]
15 | public void TestExpandRule()
16 | {
17 | var rule = new LeafRule.ExpandRule("short7", "expand");
18 | Assert.AreEqual(rule.Match("short7ending").Short, "short7");
19 | Assert.AreEqual(rule.Match("short7ending").Expand, "expand");
20 | Assert.AreEqual(rule.Match("short7").Short, "short7");
21 | Assert.AreEqual(rule.Match("short7short7").Short, "short7");
22 | Assert.IsFalse(rule.Match("wr").Success);
23 | }
24 |
25 | [Test]
26 | public void TestNonTerminal()
27 | {
28 | Assert.Throws(() =>
29 | {
30 | var rule = new LeafRule.NonTerminal("short7");
31 | rule.Match("wr");
32 | });
33 | }
34 |
35 | [Test]
36 | public void TestSubstitution()
37 | {
38 | var rule = new LeafRule.Substitution("hello", new List>().AsList());
39 | Assert.AreEqual(rule.Match("short7").Short, "short7");
40 | Assert.AreEqual(rule.Match("wr").Short, "wr");
41 | Assert.AreEqual(rule.Match("wr,aa").Short, "wr");
42 | Assert.AreEqual(rule.Match("wr`aa").Short, "wr");
43 | Assert.AreEqual(rule.Match("wr~aa").Short, "wr");
44 | }
45 |
46 |
47 | [Test]
48 | public void TestString()
49 | {
50 | var rule = new LeafRule.String("short7");
51 | Assert.IsTrue(rule.Match("wr").Success);
52 | Assert.AreEqual(rule.Match("wr").Expand, "short7");
53 | Assert.AreEqual(rule.Match("wr").Short, "");
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/LiveTemplateMatcherTests.cs:
--------------------------------------------------------------------------------
1 | using System.Security;
2 |
3 | using Github.Ulex.ZenSharp.Core;
4 |
5 | using Nemerle.Collections;
6 |
7 | using NUnit.Framework;
8 |
9 | namespace ZenSharp.Core.Tests
10 | {
11 | [TestFixture]
12 | internal sealed class LiveTemplateMatcherTests
13 | {
14 | private const string Scopename = "scopename";
15 |
16 | [Test]
17 | public void TestLiveTemplateMatcherTests()
18 | {
19 | var concatRule = new ConcatRule(new LeafRule[] { new LeafRule.ExpandRule("some", "Expand"), new LeafRule.ExpandRule("2", "2") }.NToList());
20 |
21 | var concatRuleAlt = new ConcatRule(new LeafRule[] { new LeafRule.ExpandRule("some", "Expand3"), new LeafRule.ExpandRule("3", "3") }.NToList());
22 |
23 | var mresult = MatcherFromRule(StartRule(concatRule, concatRuleAlt)).Match("some3", Scopename);
24 |
25 | Assert.IsFalse(mresult.Success);
26 | Assert.IsTrue(string.IsNullOrEmpty(mresult.Tail));
27 | }
28 |
29 | private static Rule StartRule(params ConcatRule[] concatRules)
30 | {
31 | return new Rule("start", concatRules.ToNList());
32 | }
33 |
34 | private static LiveTemplateMatcher MatcherFromRule(Rule rule)
35 | {
36 | var globalRules = NList.FromArray(new Rule[0]);
37 | var scope = new TreePart.Scope(new[] { rule }.NToList(), Scopename);
38 |
39 | var st = new LiveTemplateMatcher(new GenerateTree(globalRules, new[] { scope }.NToList()));
40 | return st;
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ZenSharp.Core.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ZenSharp.Core.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("36334361-e500-4240-b889-0742da1187f6")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyFileVersion("1.0.*")]
37 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/TestParser.cs:
--------------------------------------------------------------------------------
1 | using Github.Ulex.ZenSharp.Core;
2 |
3 | using NUnit.Framework;
4 |
5 | namespace ZenSharp.Core.Tests
6 | {
7 | internal sealed class TestParser
8 | {
9 | public const string grammar1 = @"
10 |
11 | ";
12 |
13 | [Test]
14 | public void TestTestParser()
15 | {
16 | var parser = new LtgParser();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/ZenSharp.Core.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Debug
7 | AnyCPU
8 | {1390A507-A540-4FCD-B2F5-5455D21F35F6}
9 | Library
10 | Properties
11 | ZenSharp.Core.Tests
12 | ZenSharp.Core.Tests
13 | v4.5
14 | 512
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | ..\..\bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | false
26 |
27 |
28 | pdbonly
29 | true
30 | ..\..\bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 | false
35 |
36 |
37 |
38 | ..\..\packages\AsyncBridge.Net35.0.2.0\lib\net35-Client\AsyncBridge.Net35.dll
39 |
40 |
41 | ..\..\packages\JetBrains.Lifetimes.2021.1.0\lib\net35\JetBrains.Lifetimes.dll
42 |
43 |
44 |
45 |
46 | ..\..\packages\NUnit.3.11.0\lib\net45\nunit.framework.dll
47 | True
48 |
49 |
50 |
51 |
52 | ..\..\packages\TaskParallelLibrary.1.0.2856.0\lib\Net35\System.Threading.dll
53 | True
54 | True
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | True
66 | True
67 | ExpandTestGenerator.tt
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | TextTemplatingFileGenerator
79 | ExpandTestGenerator.cs
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | {efa574e2-de9c-4017-bb5c-8fc4cd8d5e80}
89 | ZenSharp.Core
90 |
91 |
92 |
93 |
94 |
95 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.
96 |
97 |
98 |
99 |
106 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ZenSharp.Core.nproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | efa574e2-de9c-4017-bb5c-8fc4cd8d5e80
9 | Library
10 | Properties
11 | Github.Ulex.ZenSharp.Core
12 | ZenSharp.Core
13 | v4.6.1
14 | 512
15 | true
16 | Net-4.0
17 | $(ProgramFiles)\Nemerle
18 | $(NemerleBinPathRoot)\$(NemerleVersion)
19 | ZenSharp.Core
20 |
21 |
22 |
23 |
24 | true
25 | false
26 | ..\bin\Debug\
27 | DEBUG;TRACE
28 | prompt
29 | 4
30 |
31 |
32 | false
33 | true
34 | ..\bin\Release\
35 | TRACE
36 | prompt
37 | 4
38 | $(OutputPath)\$(AssemblyName).xml
39 |
40 |
41 |
42 | Nemerle.Peg.Macros
43 | Nemerle.Peg.Macros.dll
44 | $(Nemerle)\Nemerle.Peg.Macros.dll
45 | True
46 | False
47 |
48 |
49 |
50 | Nemerle
51 | Nemerle.dll
52 | $(Nemerle)\Nemerle.dll
53 | True
54 | False
55 |
56 |
57 | Nemerle.Peg
58 | Nemerle.Peg.dll
59 | $(Nemerle)\Nemerle.Peg.dll
60 | True
61 | False
62 |
63 |
64 |
65 | System.Core
66 | System.Core.dll
67 | ..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll
68 |
69 |
70 |
71 |
72 |
73 |
74 | Code
75 |
76 |
77 | Code
78 |
79 |
80 | Code
81 |
82 |
83 | Code
84 |
85 |
86 | Code
87 |
88 |
89 | Code
90 |
91 |
92 | Code
93 |
94 |
95 | Code
96 |
97 |
98 |
99 | Code
100 |
101 |
102 | Code
103 |
104 |
105 | Code
106 |
107 |
108 | Code
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
125 |
--------------------------------------------------------------------------------
/ZenSharp.Core/build.bat:
--------------------------------------------------------------------------------
1 | @SET PATH=%PATH%;C:\Program Files (x86)\Nemerle\net-4.0
2 | @SET PATH=%PATH%;C:\Windows\Microsoft.NET\Framework64\v4.0.30319
3 |
4 | msbuild /t:Build /p:Configuration=Debug ZenSharp.Core.nproj
5 |
--------------------------------------------------------------------------------
/ZenSharp.Core/ltg.vim:
--------------------------------------------------------------------------------
1 | " Vim syntax file
2 | " Language: BNF
3 | " Maintainer: Michael Brailsford, Alexander Ulitin
4 | " Last Change: Arpril 03, 2014
5 |
6 | " Quit when a syntax file was already loaded {{{
7 | if version < 600
8 | syntax clear
9 | elseif exists("b:current_syntax")
10 | finish
11 | endif
12 | "}}}
13 |
14 | syn match bnfNonTerminal "\a\w*"
15 | syn region bnfProduction start="^\s*\a" end="::="me=e-3
16 | syn region bnfComment start="^\s*//" end="$"
17 | syn region ltgSub start="<\s*" end="\>" contains=bnfString
18 | syn match bnfOr "|\|{\|}\|="
19 | syn match bnfSeperator "::="
20 | syn match bnfComment "#.*$"
21 | syn region bnfString start=+"+ skip=+""+ end=+"+
22 |
23 | syn match bnfTerminal "\\w"
24 | syn keyword bnfScopeKw scope contained
25 | syn match bnfScope #scope[^{]*{# contains=bnfScopeKw,bnfOr,bnfString
26 |
27 | hi link bnfNonTerminal Type
28 | hi link bnfProduction Identifier
29 | hi link bnfOr Operator
30 | hi link bnfSeperator PreProc
31 | hi link bnfTerminal Constant
32 | hi link bnfComment Comment
33 | hi link bnfScopeKw Keyword
34 | hi link bnfTerminalRange bnfTerminal
35 | hi link bnfString String
36 | hi link bnfLiteral String
37 | hi link ltgSub Conditional
38 |
39 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/CSharpExtendedScopeProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using JetBrains.Application;
5 | using JetBrains.DocumentModel;
6 | using JetBrains.ReSharper.Feature.Services.CSharp.CodeCompletion;
7 | using JetBrains.ReSharper.Feature.Services.LiveTemplates.Context;
8 | using JetBrains.ReSharper.Feature.Services.LiveTemplates.LiveTemplates;
9 | using JetBrains.ReSharper.Psi;
10 | using JetBrains.ReSharper.Psi.CSharp;
11 | using JetBrains.ReSharper.Psi.CSharp.Tree;
12 | using JetBrains.ReSharper.Psi.Files;
13 | using JetBrains.ReSharper.Psi.Tree;
14 | using JetBrains.ReSharper.Resources.Shell;
15 |
16 | namespace Github.Ulex.ZenSharp.Integration
17 | {
18 | [ShellComponent]
19 | public sealed class CSharpExtendedScopeProvider
20 | {
21 | ///
22 | /// Too lazy to implement full ITemplateScopePoint
23 | ///
24 | public IEnumerable ProvideScopePoints(TemplateAcceptanceContext tacContext)
25 | {
26 | var solution = tacContext.Solution;
27 | var document = tacContext.SelectionRange.Document;
28 | if (document == null)
29 | {
30 | return Array.Empty();
31 | }
32 | var psiSource = tacContext.SourceFile;
33 | if (psiSource == null)
34 | {
35 | return Array.Empty();
36 | }
37 |
38 | var points = new List();
39 | using (ReadLockCookie.Create())
40 | {
41 | var psiFiles = solution.GetPsiServices().Files;
42 | if (!psiFiles.AllDocumentsAreCommitted)
43 | {
44 | psiFiles.CommitAllDocuments();
45 | }
46 | int caretOffset = tacContext.CaretOffset.Offset;
47 | string prefix = LiveTemplatesManager.GetPrefix(document, caretOffset);
48 | var documentRange = new DocumentRange(document, caretOffset - prefix.Length);
49 | if (!documentRange.IsValid())
50 | {
51 | return Enumerable.Empty();
52 | }
53 |
54 | points.Add(psiSource.PrimaryPsiLanguage.Name);
55 |
56 | var file = psiSource.GetPsiFile(documentRange);
57 | if (file == null || !Equals(file.Language, CSharpLanguage.Instance))
58 | {
59 | return points;
60 | }
61 | var element = file.FindTokenAt(document, caretOffset - prefix.Length);
62 | if (element == null)
63 | {
64 | return points;
65 | }
66 |
67 | points.Add("InCSharpFile");
68 | var treeNode = element;
69 |
70 | if (treeNode.GetContainingNode(true) != null) return points;
71 |
72 | if (treeNode is ICSharpCommentNode || treeNode is IPreprocessorDirective)
73 | {
74 | treeNode = treeNode.PrevSibling;
75 | }
76 | if (treeNode == null)
77 | {
78 | return points;
79 | }
80 |
81 | var context = CSharpReparseContext.FindContext(treeNode);
82 | if (context == null)
83 | {
84 | return points;
85 | }
86 |
87 | if (treeNode.GetContainingNode() != null)
88 | {
89 | points.Add("InCSharpEnum");
90 | }
91 |
92 | var containingType = treeNode.GetContainingNode(true);
93 | if (containingType == null && TestNode(context, "namespace N {}", false))
94 | {
95 | points.Add("InCSharpTypeAndNamespace");
96 | }
97 | else if (TestNode(context, "void foo() {}", false))
98 | {
99 | points.Add("InCSharpTypeMember");
100 | // Extend here:
101 | // Already in type member,
102 | if (treeNode.GetContainingNode() != null)
103 | {
104 | points.Add("InCSharpInterface");
105 | }
106 | if (treeNode.GetContainingNode() != null)
107 | {
108 | points.Add("InCSharpClass");
109 | }
110 | if (treeNode.GetContainingNode() != null)
111 | {
112 | points.Add("InCSharpStruct");
113 | }
114 | if (treeNode.GetContainingNode() != null)
115 | {
116 | points.Add("InCSharpRecord");
117 | }
118 | }
119 | else
120 | {
121 | bool acceptsExpression = TestNode(context, "a++", true);
122 | if (TestNode(context, "break;", false))
123 | {
124 | points.Add("InCSharpStatement");
125 | }
126 | else if (acceptsExpression)
127 | {
128 | points.Add("InCSharpExpression");
129 | }
130 | if (!acceptsExpression && TestNode(context, "select x", false))
131 | {
132 | points.Add("InCSharpQuery");
133 | }
134 | }
135 | }
136 |
137 | return points;
138 | }
139 |
140 | private static bool TestNode(CSharpReparseContext context, string text, bool strictStart = false)
141 | where T : ITreeNode
142 | {
143 | var node = context.Parse(text);
144 | var tokenAt1 = node.FindTokenAt(new TreeOffset(context.WholeTextLength - 1));
145 | var treeTextOffset = new TreeOffset(context.OriginalTextLength);
146 | var tokenAt2 = node.FindTokenAt(treeTextOffset);
147 | if (tokenAt1 == null || tokenAt2 == null)
148 | {
149 | return false;
150 | }
151 | var errorNodeFinder = new ErrorNodeFinder(tokenAt1);
152 | errorNodeFinder.FindLastError(node);
153 | if (errorNodeFinder.Error != null
154 | && errorNodeFinder.Error.GetTreeStartOffset().Offset >= context.OriginalTextLength)
155 | {
156 | return false;
157 | }
158 | ITreeNode commonParent = tokenAt2.FindCommonParent(tokenAt1);
159 | if (!(commonParent is T))
160 | {
161 | return false;
162 | }
163 | if (strictStart)
164 | {
165 | return commonParent.GetTreeTextRange().StartOffset == treeTextOffset;
166 | }
167 | return true;
168 | }
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/EditConfigActionHandler.cs:
--------------------------------------------------------------------------------
1 | using JetBrains.Application.DataContext;
2 | using JetBrains.Application.Settings;
3 | using JetBrains.Application.UI.Actions;
4 | using JetBrains.Application.UI.Actions.MenuGroups;
5 | using JetBrains.Application.UI.ActionsRevised.Menu;
6 | using JetBrains.Application.UI.ActionSystem.ActionsRevised.Menu;
7 | using JetBrains.Diagnostics;
8 | using JetBrains.IDE;
9 | using JetBrains.ProjectModel;
10 | using JetBrains.ProjectModel.DataContext;
11 | using JetBrains.ReSharper.Resources.Shell;
12 | using JetBrains.Util;
13 |
14 | namespace Github.Ulex.ZenSharp.Integration
15 | {
16 | [ActionGroup(ActionGroupInsertStyles.Embedded)]
17 | public class ZenSharpGroup : IAction, IInsertLast
18 | {
19 | public ZenSharpGroup(Separator sep, EditConfigActionHandler handler)
20 | {
21 | }
22 | }
23 |
24 | [Action("Edit ZenSharp templates")]
25 | public class EditConfigActionHandler : IExecutableAction
26 | {
27 | public bool Update(IDataContext context, ActionPresentation presentation, DelegateUpdate nextUpdate)
28 | {
29 | var solution = context.GetData(ProjectModelDataConstants.SOLUTION);
30 | return solution != null;
31 | }
32 |
33 | public void Execute(IDataContext context, DelegateExecute nextExecute)
34 | {
35 | var store = Shell.Instance.GetComponent();
36 | var ctx = store.BindToContextTransient(ContextRange.ApplicationWide);
37 | var settings = ctx.GetKey(SettingsOptimization.DoMeSlowly);
38 |
39 | var solution = context.GetData(ProjectModelDataConstants.SOLUTION).NotNull("solution != null");
40 | var fsp = VirtualFileSystemPath.CreateByCanonicalPath(ZenSharpSettings.GetTreePath(settings.TreeFilename), InteractionContext.Local);
41 | solution.GetComponent().OpenFileAsync(fsp, OpenFileOptions.DefaultActivate);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/Extension/LeafSubstitution.cs:
--------------------------------------------------------------------------------
1 | using Github.Ulex.ZenSharp.Core;
2 |
3 | namespace Github.Ulex.ZenSharp.Integration.Extension
4 | {
5 | internal static class LeafSubstitution
6 | {
7 | public static string Macros(this LeafRule.Substitution rule)
8 | {
9 | return rule["macros"];
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/ZenSharp.Integration/Extension/MatchResultExtension.cs:
--------------------------------------------------------------------------------
1 | using Github.Ulex.ZenSharp.Core;
2 |
3 | namespace Github.Ulex.ZenSharp.Integration.Extension
4 | {
5 | internal static class MatchResultExtension
6 | {
7 | public static string ExpandDisplay(this LiveTemplateMatcher.MatchResult match, string prefix)
8 | {
9 | return match.Expand(prefix).Replace("$END$", string.Empty);
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/ZenSharp.Integration/LtgConfigWatcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using Github.Ulex.ZenSharp.Core;
4 | using JetBrains.Application;
5 | using JetBrains.Application.Settings;
6 | using JetBrains.DataFlow;
7 | using JetBrains.Lifetimes;
8 | using JetBrains.Util;
9 | using JetBrains.Util.Logging;
10 |
11 | namespace Github.Ulex.ZenSharp.Integration
12 | {
13 | [ShellComponent]
14 | internal sealed class LtgConfigWatcher : IDisposable
15 | {
16 | private static readonly ILogger Log = Logger.GetLogger(typeof(LtgConfigWatcher));
17 |
18 | private readonly IContextBoundSettingsStoreLive _boundSettings;
19 |
20 | private FileSystemWatcher _watcher;
21 |
22 | private GenerateTree _tree;
23 | private IProperty _filepath;
24 |
25 | public LtgConfigWatcher(Lifetime lifetime, ISettingsStore settingsStore)
26 | {
27 | _boundSettings = settingsStore.BindToContextLive(lifetime, ContextRange.ApplicationWide);
28 | _filepath = _boundSettings.GetValueProperty(lifetime, _boundSettings.Schema.GetScalarEntry((ZenSharpSettings s) => s.TreeFilename), null);
29 |
30 | _filepath.Change.Advise_HasNew(lifetime, v => Initialize(v.New));
31 | }
32 |
33 | private void Initialize(string settingsPath)
34 | {
35 | var path = ZenSharpSettings.GetTreePath(settingsPath);
36 | try
37 | {
38 | ReinitializeWatcher(path);
39 | WriteDefaultTemplates(path);
40 | Reload(path);
41 | }
42 | catch (Exception e)
43 | {
44 | Log.Error(e);
45 | }
46 | }
47 |
48 | private void WriteDefaultTemplates(string path)
49 | {
50 | if (!File.Exists(path))
51 | {
52 | Log.Info("Saving default templates to {0}", path);
53 | using (var resStream = typeof(LtgConfigWatcher).Assembly.GetManifestResourceStream("Github.Ulex.ZenSharp.Integration.Templates.ltg"))
54 | {
55 | if (resStream != null)
56 | {
57 | using (var fstream = File.OpenWrite(path))
58 | {
59 | resStream.CopyTo(fstream);
60 | }
61 | }
62 | }
63 | }
64 | }
65 |
66 | public void ReinitializeWatcher(string path)
67 | {
68 | if (_watcher != null)
69 | {
70 | var watcher = _watcher;
71 | _watcher = null;
72 | watcher.Dispose();
73 | }
74 |
75 | var directoryName = Path.GetDirectoryName(path);
76 | Log.Info("Create file system watcher on directory {0}", directoryName);
77 | _watcher = new FileSystemWatcher(directoryName, "*.ltg")
78 | {
79 | EnableRaisingEvents = true,
80 |
81 | // visual studio 2013 save file to temporary and rename it
82 | NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime
83 | };
84 | _watcher.Changed += (sender, args) => SafeReload(path);
85 | }
86 |
87 | private void SafeReload(string path)
88 | {
89 | try
90 | {
91 | Log.Info("Reloading config from {0}", path);
92 | Reload(path);
93 | }
94 | catch (Exception e)
95 | {
96 | Log.Error("Error updating ltg config:");
97 | MessageBox.ShowError(string.Format("Sorry for this stupid notification type, but some problem occupied when loading ZenSharp config: {0}", e.Message), "ZenSharp error");
98 | }
99 | }
100 |
101 | public GenerateTree Tree
102 | {
103 | get
104 | {
105 | return _tree;
106 | }
107 | }
108 |
109 | public void Reload(string file)
110 | {
111 | try
112 | {
113 | var path = file;
114 | _tree = new LtgParser().ParseAll(File.ReadAllText(path));
115 | Log.Info("Config reloaded from {0}", path);
116 | }
117 | catch (Exception e)
118 | {
119 | Log.Error("Error loading config", e);
120 | throw;
121 | }
122 | }
123 |
124 | public void Dispose()
125 | {
126 | _watcher.Dispose();
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/Option/ExceptionConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace Github.Ulex.ZenSharp.Integration
6 | {
7 | internal sealed class ExceptionConverter : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
10 | {
11 | var exception = value as Exception;
12 | if (exception == null || targetType != typeof(string))
13 | {
14 | return null;
15 | }
16 |
17 | return string.Format("{0}{1}{2}", exception.Message, Environment.NewLine, exception.StackTrace);
18 | }
19 |
20 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
21 | {
22 | throw new NotImplementedException();
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/ZenSharp.Integration/Option/ZenSettingsPage.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Documentation and source code available at:
30 |
31 | https://github.com/ulex/ZenSharp
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/Option/ZenSettingsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.Runtime.CompilerServices;
5 | using System.Windows;
6 | using System.Windows.Navigation;
7 | using JetBrains.Application.Settings;
8 | using JetBrains.Application.UI.Options;
9 | using JetBrains.Application.UI.Options.OptionPages;
10 | using JetBrains.Application.UI.Options.Options.ThemedIcons;
11 | using JetBrains.DataFlow;
12 | using JetBrains.Lifetimes;
13 | using JetBrains.Util;
14 | using JetBrains.Util.Logging;
15 | using Microsoft.Win32;
16 |
17 | namespace Github.Ulex.ZenSharp.Integration
18 | {
19 | ///
20 | /// Interaction logic for ZenSettingsPage.xaml
21 | ///
22 | [OptionsPage(pageId, "ZenSharp", typeof(OptionsThemedIcons.Plugins), ParentId = EnvironmentPage.Pid)]
23 | public partial class ZenSettingsPage : IOptionsPage
24 | {
25 | private const string pageId = "ZenSettingsPageId";
26 |
27 | private static readonly ILogger Log = Logger.GetLogger(typeof(ZenSettingsPage));
28 |
29 | public IProperty Path { get; private set; }
30 |
31 | public ZenSettingsPage(Lifetime lifetime, OptionsSettingsSmartContext settings)
32 | {
33 | Path = new Property("Path");
34 | settings.SetBinding(lifetime, (ZenSharpSettings s) => s.TreeFilename, Path);
35 | InitializeComponent();
36 | Id = pageId;
37 | // show exception info if any
38 | OnOk();
39 | }
40 |
41 | public string Id { get; }
42 |
43 | public bool OnOk()
44 | {
45 | return true;
46 | }
47 |
48 | private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
49 | {
50 | try
51 | {
52 | var dialog = new OpenFileDialog() { CheckFileExists = true, DefaultExt = "ltg", ValidateNames = true };
53 | if (dialog.ShowDialog() == true)
54 | {
55 | Path.Value = dialog.FileName;
56 | }
57 | }
58 | catch (Exception exception)
59 | {
60 | Log.Error("Unexcpected error", exception);
61 | }
62 | }
63 |
64 | private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e)
65 | {
66 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
67 | e.Handled = true;
68 | }
69 |
70 | public event PropertyChangedEventHandler PropertyChanged;
71 |
72 | // [NotifyPropertyChangedInvocator]
73 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
74 | {
75 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/Templates.ltg:
--------------------------------------------------------------------------------
1 | // C# templates
2 | // Sample file
3 | space ::= " "
4 | cursor ::= "$END$"
5 | cursorb ::= "(" cursor ")"
6 | // Resharper macros:
7 | identifier ::=
8 | identifier2 ::=
9 | //
10 | // Types:
11 | //
12 | suggType ::=
13 |
14 | // Primive types:
15 | maybeType ::= type | "void"
16 | type ::= generic | primType ("?"="?")? ("[]"=a)? | suggType
17 | primType ::= string=s | byte=by | bool=b | "System.DateTime"=dt | decimal=dc | double=d | int=i | uint=ui | "System.Guid"=g | "System.Uri"=u | "System.Xml.Linq.XElement"=x |
18 | object=o
19 | taskType ::= "System.Threading.Tasks.Task"
20 |
21 | // Complex types:
22 | generic1 ::= (SCG "." ("IList"=l | "IEnumerable"="~")) "<" type ">"
23 | generic2 ::= (SCG "." ("SortedList"=sl | "IDictionary"=di)) "<" type ", " type ">"
24 | SCG ::= "System.Collections.Generic"
25 | generic ::= generic1 | generic2
26 |
27 |
28 | access ::= (internal=i | public=p | private=_ | protected=P) space
29 |
30 | // Auto properties:
31 | property ::= access ("abstract "=ap | "static "=P | "virtual "=vp | ""=p) type space identifier propertyBody cursor
32 | propertyBody ::= "{ get;" propertySetAccessor " set; }"
33 | propertySetAccessor ::= "protected "="+p" | ""="+" | "private "
34 |
35 | // Methods:
36 | methodAttributes ::=
37 | | "[NUnit.Framework.SetUpAttribute]"=su
38 | | "[NUnit.Framework.TestFixtureSetUpAttribute]"=tfsu
39 | | "[NUnit.Framework.TestFixtureTearDownAttribute]"=tftd
40 | | "[NUnit.Framework.TearDownAttribute]"=td
41 | | "[NUnit.Framework.TestCaseAttribute]"=tc
42 | | "[NUnit.Framework.TestAttribute]"=t
43 | method_async ::= (methodAttributes)? access "async" space ("virtual "=vm | "abstract "=am | "static "=M | ""=m) (taskType "<"=T type ">" | taskType ""=T) space identifier methodArgs methodBody
44 | method_generic ::= (methodAttributes)? access ("virtual "=vm | "abstract "=am | "static "=M | ""=m) (type | "void") space identifier methodArgs methodBody
45 | method ::= method_async | method_generic
46 | methodBody ::= " { " cursor " }"
47 | methodArgs ::= "(" ((""="," | ""="(") arg)? ")"
48 | arg ::= primType " " identifier2
49 |
50 | // Consts:
51 | const ::= access "const "=c primType space identifier "= """ identifier """;"
52 |
53 | // Fields:
54 | field ::= access ("readonly "=r)? type space identifier ("="="=" identifier2 ";" | ";")
55 |
56 | // Classes:
57 | classAtributes ::= ("[NUnit.Framework.TestFixtureAttribute]" = tf)?
58 | class ::= classAtributes access ("sealed "=S)? ("class"=c | "static class"=C) space classBody
59 | classBody ::= identifier (" : "=":" type)? "{" cursor "}"
60 |
61 | // Records:
62 | record ::= access ("abstract "=a | "sealed "=S | "readonly "=r)? "record "=R ("struct "=s)? identifier recordArgsList record_inheritance ";"
63 | record_inheritance ::= (" : "=":" type "( " cursor " )")?
64 | recordArgsList ::= "(" ((""="," | ""="(") recordArg)? ")"
65 | recordArg ::= type " " identifier2 (", "="," recordArg)?
66 |
67 | //Enums:
68 | enum ::= access space "enum"=e space identifier "{" cursor "}"
69 |
70 | scope "InCSharpClass" {
71 | start ::= method | property | field | const | other
72 |
73 | other ::=
74 | | class
75 | | ""=dbset "public DBSet<" identifier " > " identifier "s {get; set; }"
76 | | enum
77 | | record
78 | }
79 |
80 | scope "InCSharpRecord" {
81 | start ::= property
82 | }
83 |
84 | scope "InCSharpTypeAndNamespace" {
85 | start ::=
86 | | class
87 | | interface
88 | | enum
89 | | record
90 |
91 | interface ::= access "interface"=i space classBody
92 | }
93 |
94 | scope "InCSharpInterface" {
95 | start ::=
96 | | type space identifier propertyBody cursor
97 | | method
98 | | property
99 |
100 | propertyBody ::= "{ get; }" | "{ get; set; }"="+"
101 | access ::= ""
102 | methodBody ::= ";"
103 | }
104 |
105 | scope "InCSharpStruct" {
106 | // start ::= ""
107 | }
108 |
109 | scope "InCSharpStatement" {
110 | start ::=
111 | | "if ("=ifr identifier " == null) return;"
112 | | "Log."=l (Fatal=f | Info=i | Error=e | Trace=t | Debug=d) "(""" cursor """);"
113 | }
114 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/ZenSharp.Integration.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Library
4 | Github.Ulex.ZenSharp.Integration
5 | ZenSharp.Integration
6 | net472-windows
7 | true
8 | latest
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 2024.3.0-eap01
17 | runtime; build; native; contentfiles; analyzers
18 | all
19 |
20 |
21 | False
22 | ..\bin\Release\ZenSharp.Core.dll
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/ZenSharpItemsProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using JetBrains.DocumentModel;
4 | using JetBrains.ProjectModel;
5 | using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure;
6 | using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure.LookupItems;
7 | using JetBrains.ReSharper.Feature.Services.CSharp.CodeCompletion.Infrastructure;
8 | using JetBrains.ReSharper.Feature.Services.LiveTemplates.Context;
9 | using JetBrains.ReSharper.Feature.Services.LiveTemplates.Settings;
10 | using JetBrains.ReSharper.Feature.Services.LiveTemplates.Templates;
11 | using JetBrains.ReSharper.Feature.Services.Resources;
12 | using JetBrains.ReSharper.Psi;
13 | using JetBrains.ReSharper.Resources.Shell;
14 | using JetBrains.TextControl;
15 | using JetBrains.Util;
16 | using JetBrains.Util.Logging;
17 |
18 | namespace Github.Ulex.ZenSharp.Integration
19 | {
20 | [Language(typeof(KnownLanguage))]
21 | internal class ZenSharpItemsProvider : ItemsProviderOfSpecificContext
22 | {
23 | private static readonly ILogger Log = Logger.GetLogger(typeof(ZenSharpItemsProvider));
24 |
25 | protected override bool IsAvailable(ISpecificCodeCompletionContext context)
26 | {
27 | if (context is CSharpCodeCompletionContext csContext && csContext.ReplaceRangeWithJoinedArguments.Length == 0)
28 | return false;
29 |
30 | return true;
31 | }
32 |
33 | protected override bool AddLookupItems(ISpecificCodeCompletionContext context, IItemsCollector collector)
34 | {
35 | Log.Info("Add lookupitems");
36 |
37 | var solution = context.BasicContext.Solution;
38 |
39 | var ltgConfig = Shell.Instance.GetComponent();
40 |
41 | var iconManager = solution.GetComponent();
42 | var provider = solution.GetComponent();
43 | var textControl = context.BasicContext.TextControl;
44 |
45 | var offset = textControl.Caret.Offset();
46 | var templateContext = new TemplateAcceptanceContext(
47 | solution,
48 | new DocumentOffset(textControl.Document, offset),
49 | new DocumentRange(textControl.Document, offset));
50 |
51 | var scopePoints = provider.ProvideScopePoints(templateContext);
52 | if (ltgConfig.Tree != null)
53 | {
54 | var template = new Template("", "", "", true, true, false, new[] {TemplateApplicability.Live})
55 | {
56 | UID = Guid.NewGuid()
57 | };
58 | var scopes = scopePoints.ToList();
59 | Log.Trace("Current scopes: {0}", string.Join(",", scopes));
60 |
61 | if (scopes.Any(scopename => ltgConfig.Tree.IsScopeExist(scopename)))
62 | {
63 | var iconId = iconManager.ExtendToTypicalSize(ServicesThemedIcons.LiveTemplate.Id);
64 | collector.Add(new ZenSharpLookupItem(template, ltgConfig.Tree, scopes, iconId));
65 | return true;
66 | }
67 | else
68 | {
69 | return false;
70 | }
71 | }
72 | Log.Warn("Lookup item for completion is not added, because ZenSharp expand tree is not loaded.");
73 | return false;
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/ZenSharpLookupItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Github.Ulex.ZenSharp.Core;
5 | using Github.Ulex.ZenSharp.Integration.Extension;
6 | using JetBrains.Diagnostics;
7 | using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure.LookupItems;
8 | using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure.Match;
9 | using JetBrains.ReSharper.Feature.Services.LiveTemplates;
10 | using JetBrains.ReSharper.Feature.Services.LiveTemplates.Templates;
11 | using JetBrains.ReSharper.Feature.Services.LiveTemplates.Util;
12 | using JetBrains.ReSharper.Resources.Shell;
13 | using JetBrains.Text;
14 | using JetBrains.UI.Icons;
15 | using JetBrains.UI.RichText;
16 | using JetBrains.Util;
17 | using JetBrains.Util.Logging;
18 | // using LoggingLevel = JetBrains.Diagnostics.LoggingLevel;
19 |
20 | namespace Github.Ulex.ZenSharp.Integration
21 | {
22 | ///
23 | /// todo: remove inherence
24 | ///
25 |
26 | internal class ZenSharpLookupItem : TemplateLookupItem, ILookupItem
27 | {
28 | private static readonly ILogger Log = Logger.GetLogger(typeof(ZenSharpLookupItem));
29 |
30 | private readonly IEnumerable _scopes;
31 |
32 | ///
33 | /// todo: remove
34 | ///
35 | private readonly Template _template;
36 |
37 | private readonly GenerateTree _tree;
38 |
39 | private readonly IconId _iconId;
40 |
41 | private string _displayName;
42 |
43 | public ZenSharpLookupItem(Template template, GenerateTree tree, IEnumerable scopes, IconId iconId)
44 | : base(template, true, Shell.Instance.GetComponent())
45 | {
46 | _tree = tree;
47 | _scopes = scopes;
48 | _template = template;
49 | Log.Info("Creating ZenSharpLookupItem with template = {0}", template);
50 | _iconId = iconId;
51 | _displayName = _template.Text;
52 | }
53 |
54 | RichText ILookupItem.DisplayName
55 | {
56 | get { return new RichText(_displayName); }
57 | }
58 |
59 | bool ILookupItem.CanShrink
60 | {
61 | get { return true; }
62 | }
63 |
64 | IconId ILookupItem.Image
65 | {
66 | get { return _iconId; }
67 | }
68 |
69 | bool ILookupItem.IsDynamic
70 | {
71 | get { return true; }
72 | }
73 |
74 | bool ILookupItem.AcceptIfOnlyMatched(LookupItemAcceptanceContext itemAcceptanceContext)
75 | {
76 | return true;
77 | }
78 |
79 | MatchingResult ILookupItem.Match(PrefixMatcher prefixMatcher)
80 | {
81 | string prefix = prefixMatcher.Prefix;
82 | if (string.IsNullOrEmpty(prefix)) return null;
83 |
84 | Log.Info("Match prefix = {0}", prefix);
85 | if (_tree == null)
86 | {
87 | Log.Error("Expand tree is null, return.");
88 | return null;
89 | }
90 |
91 | var matcher = new LiveTemplateMatcher(_tree);
92 | var matchedScopes = _scopes.Where(s => _tree.IsScopeExist(s)).ToList();
93 | Log.Trace("Matched scopes = {0}", string.Join(", ", matchedScopes));
94 |
95 | if (matchedScopes.Count == 0)
96 | {
97 | return null;
98 | }
99 |
100 | foreach (var scope in matchedScopes)
101 | {
102 | try
103 | {
104 | var matchingResult = GetMatchingResult(prefix, matcher, scope);
105 | if (matchingResult != null)
106 | {
107 | return matchingResult;
108 | }
109 | }
110 | catch (Exception e)
111 | {
112 | Log.LogException(LoggingLevel.ERROR, e, ExceptionOrigin.Assertion, "Exception during match");
113 | return null;
114 | }
115 | }
116 | return null;
117 | }
118 |
119 | private MatchingResult GetMatchingResult(string prefix, LiveTemplateMatcher matcher, string scopeName)
120 | {
121 | var matchResult = matcher.Match(prefix, scopeName);
122 | if (matchResult.Success)
123 | {
124 | FillText(prefix, matchResult);
125 | Log.Info("Successfull match in scope [{1}]. Return [{0}]", matchResult, scopeName);
126 | return CreateMatchingResult(prefix);
127 | }
128 | else if (matchResult.Suggestion != null && string.IsNullOrEmpty(matchResult.Suggestion.Tail))
129 | {
130 | FillText(prefix, matchResult.Suggestion);
131 | Log.Info("Suggestion match in scope [{1}] with result [{0}]", matchResult, scopeName);
132 |
133 | return CreateMatchingResult(prefix);
134 | }
135 | else
136 | {
137 | Log.Info("No completition found for {0} in scope {1}", prefix, scopeName);
138 | return null;
139 | }
140 | }
141 |
142 | private static MatchingResult CreateMatchingResult(string prefix)
143 | {
144 | // todo: review parameters
145 | var enableAllFlags = MatcherScore.Highest - 1;
146 | return new MatchingResult(prefix.Length, 1, enableAllFlags);
147 | }
148 |
149 | private string FillText(string prefix, LiveTemplateMatcher.MatchResult matchResult)
150 | {
151 | var matchExpand = matchResult.Expand(prefix);
152 | Log.Trace("Template text: {0}", matchExpand);
153 | if (!string.IsNullOrEmpty(matchExpand))
154 | {
155 | _template.Text = matchExpand;
156 | _displayName = matchResult.ExpandDisplay(prefix);
157 |
158 | FillMacros(prefix, matchResult);
159 | }
160 | return matchExpand;
161 | }
162 |
163 | private void FillMacros(string prefix, LiveTemplateMatcher.MatchResult matchResult)
164 | {
165 | _template.Fields.Clear();
166 | var appliedRules = matchResult.ReMatchLeafs(prefix);
167 | var appliedSubsNames = new List();
168 | foreach (var subst in appliedRules.Where(ar => ar.This is LeafRule.Substitution))
169 | {
170 | var rule = (LeafRule.Substitution)subst.This;
171 | if (!appliedSubsNames.Contains(rule.Name))
172 | {
173 | appliedSubsNames.Add(rule.Name);
174 |
175 | var macros = rule.Macros();
176 | if (string.IsNullOrEmpty(macros))
177 | {
178 | macros = "complete()";
179 | }
180 | else
181 | {
182 | macros = macros.Replace("\\0", subst.Short);
183 | }
184 | Log.Trace("Place holder macro: {0}, {1}", macros, rule.Name);
185 | _template.Fields.Add(new TemplateField(rule.Name, macros, 0));
186 | }
187 | }
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/ZenSharpSettings.cs:
--------------------------------------------------------------------------------
1 | using JetBrains.Util;
2 |
3 | using System;
4 | using System.IO;
5 | using JetBrains.Application.Settings;
6 | using JetBrains.ReSharper.Resources.Settings;
7 |
8 | namespace Github.Ulex.ZenSharp.Integration
9 | {
10 | [SettingsKey(typeof(PatternsAndTemplatesSettingsKey), "ZenSharp settings")]
11 | public sealed class ZenSharpSettings
12 | {
13 | [SettingsEntry("Templates.ltg", "Path to ltg file")]
14 | public string TreeFilename { get; set; }
15 |
16 | public static string GetTreePath(string treeFilename)
17 | {
18 | if (treeFilename.IsNullOrEmpty())
19 | {
20 | return null;
21 | }
22 | if (!string.IsNullOrEmpty(treeFilename) && Path.IsPathRooted(treeFilename))
23 | {
24 | return treeFilename;
25 | }
26 | else
27 | {
28 | return Path.Combine(DefaultDir, treeFilename);
29 | }
30 | }
31 |
32 | private static string DefaultDir
33 | {
34 | get
35 | {
36 | // todo: store ltg iside ReSharper config
37 | return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/ZoneMarker.cs:
--------------------------------------------------------------------------------
1 | using JetBrains.Application.BuildScript.Application.Zones;
2 | using JetBrains.Platform.VisualStudio.Protocol.Zones;
3 | using JetBrains.ReSharper.Psi.CSharp;
4 | using JetBrains.TextControl;
5 |
6 | namespace Github.Ulex.ZenSharp.Integration
7 | {
8 | [ZoneDefinition(ZoneFlags.AutoEnable)]
9 | [ZoneDefinitionConfigurableFeature("ZenSharp", "ZenSharp auto completion", false)]
10 | public interface IZenSharpZoneDefinition : IZone, IRequire, IRequire, ILanguageCSharpZone
11 | {
12 | }
13 |
14 | [ZoneMarker]
15 | public class ZoneMarker : IRequire
16 | {
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | Templates.ltg
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ZenSharp.Integration/resharper_macros.71.txt:
--------------------------------------------------------------------------------
1 | // getCreationTime
2 | // Date and time when the file was created in specified {#0:format}
3 | // Evaluates file creation date and time
4 | // P: String
5 |
6 | // list
7 | // {#0:Comma-delimited list of values}
8 | // Displays the specified list of values.
9 | // P: String
10 |
11 | // spacestounderstrokes
12 | // Value of {#0:another variable}, where spaces will be replaced with '_'
13 | // Changes spaces to '_' (i.e. "do something usefull" into "do_something_usefull"
14 | // P: VariableReference
15 |
16 | // arrayVariable
17 | // Suggest an array variable
18 | // Suggests variable which type is array type
19 |
20 | // fixedTypeName
21 | // Insert reference to {#0:type}
22 | // Evaluates to selected type name.
23 | // P: Type
24 |
25 | // capitalize
26 | // Value of {#0:another variable} with the first character in upper case
27 | // Capitalizes string value (i.e. changes case of the first letter to upper)
28 | // P: VariableReference
29 |
30 | // clipboard
31 | // Clipboard content
32 | // Evaluates to current textual clipboard content
33 |
34 | // complete
35 | // Execute basic completion
36 | // Show basic code completion list at the point where the variable is evaluated
37 |
38 | // completeSmart
39 | // Execute smart completion
40 | // Show smart code completion list at the point where the variable is evaluated
41 |
42 | // completeType
43 | // Execute type completion
44 | // Show type completion list at the point where the variable is evaluated
45 | // P: Type
46 |
47 | // constant
48 | // {#0:Constant value}
49 | // Evaluates to the specified constant value.
50 | // P: String
51 |
52 | // typeMember
53 | // Containing type member name
54 | // Evaluates to short name of the most inner containing type member (e.g. method or property).
55 |
56 | // typeName
57 | // Containing type name
58 | // Evaluates to short name of the most inner containing type.
59 |
60 | // context
61 | // Provides list of items describing current context
62 | // Provides list of items describing current context. This includes file name, containing type name, namespace name, etc.
63 |
64 | // getCurrentDate
65 | // Current date in specified {#0:format}
66 | // Evaluates current date
67 | // P: String
68 |
69 | // getCurrentTime
70 | // Current date and time in specified {#0:format}
71 | // Evaluates current date
72 | // P: String
73 |
74 | // getCurrentNamespace
75 | // Containing namespace
76 | // Evaluates name of the containing namespace
77 |
78 | // decapitalize
79 | // Value of {#0:another variable} with the first character in lower case
80 | // Decapitalizes string value (i.e. changes case of the first letter to lower)
81 | // P: VariableReference
82 |
83 | // getDefaultNamespace
84 | // Default namespace
85 | // Gets default namespace for the current project
86 |
87 | // fileDefaultNamespace
88 | // Default namespace for current file
89 | // Gets default namespace for the current file
90 |
91 | // getFileName
92 | // Current file name
93 | // Evaluates current file name
94 |
95 | // getFileNameWithoutExtension
96 | // Current file name without extension
97 | // Evaluates current file name without extension
98 |
99 | // getFullUserName
100 | // Full user name of the current user
101 | // Evaluates full name of the current user
102 |
103 | // guessElementType
104 | // Guess element type of collection represented by {#0:variable}
105 | // Analyzes code and guesses type of element of a collection.
106 | // P: VariableReference
107 |
108 | // guessExpectedElementType
109 | // Guess element type for expected collection type
110 | // Guess element type if a collection type is expected at this point
111 |
112 | // guessExpectedType
113 | // Guess type expected at this point
114 | // Guess type expected at this point
115 | // P: Type
116 |
117 | // guessKeyType
118 | // Guess key type of dictionary represented by {#0:variable}
119 | // Analyzes code and guesses type of key of a dictionary collection.
120 | // P: VariableReference
121 |
122 | // guessValueType
123 | // Guess value type of dictionary represented by {#0:variable}
124 | // Analyzes code and guesses type of value of a dictionary collection.
125 | // P: VariableReference
126 |
127 | // guid
128 | // New GUID
129 | // Generates new Globally Unique Identifier (GUID)
130 |
131 | // lineNumber
132 | // Current line number
133 | // Evaluates to number of the line macro is evaluated at.
134 |
135 | // getOutputName
136 | // Current project output assembly name
137 | // Evaluates output assembly name for the current project
138 |
139 | // parameterOfType
140 | // Suggest parameter of {#0:type}
141 | // Suggests parameters of the specified type.
142 | // P: Type
143 |
144 | // getProjectName
145 | // Name of the current project
146 | // Evaluates current project name
147 |
148 | // getSolutionName
149 | // Current solution name
150 | // Evaluates current solution name
151 |
152 | // enumerableVariable
153 | // Suggest enumerable variable
154 | // Suggests visible variable that can be enumerated (that is, used in foreach loop as collection)
155 |
156 | // suggestIndexVariable
157 | // Suggest name for an index variable
158 | // Suggests non-used name which can be used for an index variable at the evaluation point.
159 |
160 | // suggestVariableName
161 | // Suggest name for a variable
162 | // When exectuted in variable declaration (where variable name should stand), suggests name for the variable.
163 |
164 | // variableOfType
165 | // Suggest variable of {#0:type}
166 | // Suggests variables of the specified type.
167 | // P: Type
168 |
169 | // suggestVariableType
170 | // Suggest type for a new variable
171 | // Suggest type for a new variable declared in the template
172 |
173 | // getUserName
174 | // Short name of the current user
175 | // Evaluates current user name
176 |
177 | // dependancyPropertyType
178 | // DependencyProperty type
179 | // Evaluates to dependency property type specific to current framework
180 |
181 | // suggestAttributeNameByTag
182 | // Suggests attribute name by tag
183 | // Suggests attribute name used in the same tags in current document
184 |
185 | // suggestAttributeValue
186 | // Suggest attribute value
187 | // Suggest attribute value for current html tag attribute
188 |
189 | // suggestTagName
190 | // Suggests tag name
191 | // Suggests tag name used in current document
192 |
193 | // AspMasterpageContentGenerator
194 | // ASP.NET Masterpage content generator
195 | // Generate content for masterpage content placeholders at the point where the variable is evaluated
196 |
197 | // AspMvcController
198 | // ASP.NET MVC Controller
199 | // Show completion list with available ASP.NET MVC Controllers at the point where the variable is evaluated
200 |
201 | // AspMvcAction
202 | // ASP.NET MVC Action
203 | // Show completion list with available ASP.NET MVC Actions at the point where the variable is evaluated
204 |
205 | // runAtServer
206 | // Insert runat="server" if server-side tag selected
207 | // Insert runat="server" if server-side tag selected
208 |
209 | // fileheader
210 | // File header
211 | // Inserts the file header specified in the ReSharper options.
212 |
213 | // castToLeftSideType
214 | // Cast to the required type (if the cast is necessary)
215 | // Inserts (if required) cast to the type which is expected at the left side of assignment expression.
216 |
217 | // fullTagName
218 | // Full tag name
219 | // Inserts full name of containing tag
220 |
221 | // suggestXmlAttributeNameByTag
222 | // Suggests XML attribute name by tag
223 | // Suggests XML attribute name used in the same tags in current document
224 |
225 | // suggestAttributeName
226 | // Suggests XML attribute name
227 | // Suggests XML attribute name used in current document
228 |
229 | // suggestXmlTagName
230 | // Suggests XML tag name
231 | // Suggests XML tag name used in current document
232 |
233 | // tagName
234 | // Tag name
235 | // Inserts name of containing tag without namespace
236 |
237 | // tagNamespace
238 | // Tag namespace
239 | // Inserts namespace of containing tag
240 |
241 |
--------------------------------------------------------------------------------
/ZenSharp.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $PackageId$
5 | $PackageVersion$
6 | ZenSharp auto completion plugin
7 | Alexander Ulitin
8 |
9 | A shortcuts language for defining ReSharper live template items. You can specify your own live template scheme using flexible language.
10 | Free and open source. For more information, see Github.
11 |
12 |
13 | Support 2024.3 eap 1 +
14 |
15 | Alexander Ulitin
16 | livetemplates code completion ltg
17 | https://github.com/ulex/ZenSharp
18 | https://raw.github.com/ulex/IntroduceNsAlias/master/icon.png
19 | https://opensource.org/licenses/MIT
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/ZenSharp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31521.260
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{EDCC3B85-0BAD-11DB-BC1A-00112FDE8B61}") = "ZenSharp.Core", "ZenSharp.Core\ZenSharp.Core.nproj", "{EFA574E2-DE9C-4017-BB5C-8FC4CD8D5E80}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZenSharp.Core.Tests", "ZenSharp.Core\ZenSharp.Core.Tests\ZenSharp.Core.Tests.csproj", "{1390A507-A540-4FCD-B2F5-5455D21F35F6}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{DAADCB1B-EC51-4030-A54B-C037312AC013}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7D63C907-EF8D-43B0-B94A-18A316C8D6C0}"
13 | ProjectSection(SolutionItems) = preProject
14 | build.bat = build.bat
15 | buildNuPack.ps1 = buildNuPack.ps1
16 | ZenSharp.nuspec = ZenSharp.nuspec
17 | EndProjectSection
18 | EndProject
19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZenSharp.Integration", "ZenSharp.Integration\ZenSharp.Integration.csproj", "{0F533A6E-E130-11E4-88A7-74D435B9EFD1}"
20 | EndProject
21 | Global
22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
23 | Debug|Any CPU = Debug|Any CPU
24 | Release|Any CPU = Release|Any CPU
25 | EndGlobalSection
26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
27 | {EFA574E2-DE9C-4017-BB5C-8FC4CD8D5E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
28 | {EFA574E2-DE9C-4017-BB5C-8FC4CD8D5E80}.Debug|Any CPU.Build.0 = Debug|Any CPU
29 | {EFA574E2-DE9C-4017-BB5C-8FC4CD8D5E80}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {EFA574E2-DE9C-4017-BB5C-8FC4CD8D5E80}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {1390A507-A540-4FCD-B2F5-5455D21F35F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | {1390A507-A540-4FCD-B2F5-5455D21F35F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | {1390A507-A540-4FCD-B2F5-5455D21F35F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | {0F533A6E-E130-11E4-88A7-74D435B9EFD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {0F533A6E-E130-11E4-88A7-74D435B9EFD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {0F533A6E-E130-11E4-88A7-74D435B9EFD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {0F533A6E-E130-11E4-88A7-74D435B9EFD1}.Release|Any CPU.Build.0 = Release|Any CPU
38 | EndGlobalSection
39 | GlobalSection(SolutionProperties) = preSolution
40 | HideSolutionNode = FALSE
41 | EndGlobalSection
42 | GlobalSection(NestedProjects) = preSolution
43 | {0F533A6E-E130-11E4-88A7-74D435B9EFD1} = {7D63C907-EF8D-43B0-B94A-18A316C8D6C0}
44 | EndGlobalSection
45 | GlobalSection(ExtensibilityGlobals) = postSolution
46 | SolutionGuid = {749E95FE-73F6-40C5-8C5F-D462882FEEB7}
47 | EndGlobalSection
48 | EndGlobal
49 |
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | REM SET PATH=%PATH%;C:\Windows\Microsoft.NET\Framework64\v4.0.30319
3 | SET PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin;%PATH%
4 | SET HostFullIdentifier=
5 |
6 | if not defined version set /P VERSION=Version:
7 |
8 |
9 | powershell -ExecutionPolicy bypass .\patchAssemblyInfo.ps1 %VERSION% || goto :error
10 | msbuild /t:Build /p:Configuration=Release ZenSharp.sln || goto :error
11 | powershell.exe -ExecutionPolicy ByPass -File ".\buildNuPack.ps1" || goto :error
12 | powershell -ExecutionPolicy bypass .\patchAssemblyInfo.ps1 1.0.* || goto :error
13 | pause
14 | goto :EOF
15 |
16 | :error
17 | echo "Failded with error #%errorlevel%.
18 | exit /b %errorlevel%
19 | pause
20 |
--------------------------------------------------------------------------------
/buildNuPack.ps1:
--------------------------------------------------------------------------------
1 | pushd $args[0]
2 |
3 | $nuspec = ".\ZenSharp.nuspec"
4 | $version = [System.Diagnostics.FileVersionInfo]::GetVersionInfo((gi .\bin\Release\ZenSharp.Core.dll).FullName).FileVersion
5 | write-host "Version = $version"
6 |
7 | $packages = @{
8 | "ZenSharp_R91" = @{
9 | 'PackageId' = 'Ulex.ZenSharp';
10 | 'PackageVersion' = $version;
11 | 'DependencyId' = 'Wave';
12 | 'DependencyVersion' = '243';
13 | 'IntegrationDll' = 'ZenSharp.Integration\bin\Release\net472-windows\ZenSharp.Integration.dll';
14 | 'TargetDir' = 'DotFiles\';
15 | };
16 | }
17 | foreach ($p in $packages.Values){
18 | $properties = [String]::Join(";" ,($p.GetEnumerator() | % {("{0}={1}" -f @($_.Key, $_.Value))}))
19 | write-host $properties
20 | #.\ilmerge.bat $p['IntegrationDll']
21 | nuget.exe pack $nuspec -Properties $properties
22 | }
23 |
24 | Move-Item *.nupkg .\bin\Release -Force
25 |
26 | popd
27 |
--------------------------------------------------------------------------------
/dependencies.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Nemerle",
4 | "version": "1.2.0.547",
5 | "url": "https://github.com/rsdn/nemerle",
6 | "license": "Custom license",
7 | "licenseUrl": "https://github.com/rsdn/nemerle/blob/v1.1/COPYRIGHT"
8 | }
9 | ]
10 |
--------------------------------------------------------------------------------
/doc/railroad-diagrams.css:
--------------------------------------------------------------------------------
1 | svg.railroad-diagram {
2 | background-color: hsl(30,20%,95%);
3 | }
4 | svg.railroad-diagram path {
5 | stroke-width: 3;
6 | stroke: black;
7 | fill: rgba(0,0,0,0);
8 | }
9 | svg.railroad-diagram text {
10 | font: bold 14px monospace;
11 | text-anchor: middle;
12 | }
13 | svg.railroad-diagram text.label {
14 | text-anchor: start;
15 | }
16 | svg.railroad-diagram text.comment {
17 | font: italic 12px monospace;
18 | }
19 | svg.railroad-diagram rect {
20 | stroke-width: 3;
21 | stroke: black;
22 | fill: hsl(120,100%,90%);
23 | }
24 |
--------------------------------------------------------------------------------
/doc/railroad-diagrams.js:
--------------------------------------------------------------------------------
1 | /*
2 | Railroad Diagrams
3 | by Tab Atkins Jr. (and others)
4 | http://xanthir.com
5 | http://twitter.com/tabatkins
6 | http://github.com/tabatkins/railroad-diagrams
7 |
8 | This document and all associated files in the github project are licensed under CC0: http://creativecommons.org/publicdomain/zero/1.0/
9 | This means you can reuse, remix, or otherwise appropriate this project for your own use WITHOUT RESTRICTION.
10 | (The actual legal meaning can be found at the above link.)
11 | Don't ask me for permission to use any part of this project, JUST USE IT.
12 | I would appreciate attribution, but that is not required by the license.
13 | */
14 |
15 | /*
16 | This file uses a module pattern to avoid leaking names into the global scope.
17 | The only accidental leakage is the name "temp".
18 | The exported names can be found at the bottom of this file;
19 | simply change the names in the array of strings to change what they are called in your application.
20 |
21 | As well, several configuration constants are passed into the module function at the bottom of this file.
22 | At runtime, these constants can be found on the Diagram class.
23 | */
24 |
25 | var temp = (function(options) {
26 | function subclassOf(baseClass, superClass) {
27 | baseClass.prototype = Object.create(superClass.prototype);
28 | baseClass.prototype.$super = superClass.prototype;
29 | }
30 |
31 | function unnull(/* children */) {
32 | return [].slice.call(arguments).reduce(function(sofar, x) { return sofar !== undefined ? sofar : x; });
33 | }
34 |
35 | function determineGaps(outer, inner) {
36 | var diff = outer - inner;
37 | switch(Diagram.INTERNAL_ALIGNMENT) {
38 | case 'left': return [0, diff]; break;
39 | case 'right': return [diff, 0]; break;
40 | case 'center':
41 | default: return [diff/2, diff/2]; break;
42 | }
43 | }
44 |
45 | function wrapString(value) {
46 | return ((typeof value) == 'string') ? new Terminal(value) : value;
47 | }
48 |
49 |
50 | function SVG(name, attrs, text) {
51 | attrs = attrs || {};
52 | text = text || '';
53 | var el = document.createElementNS("http://www.w3.org/2000/svg",name);
54 | for(var attr in attrs) {
55 | el.setAttribute(attr, attrs[attr]);
56 | }
57 | el.textContent = text;
58 | return el;
59 | }
60 |
61 | function FakeSVG(tagName, attrs, text){
62 | if(!(this instanceof FakeSVG)) return new FakeSVG(tagName, attrs, text);
63 | if(text) this.children = text;
64 | else this.children = [];
65 | this.tagName = tagName;
66 | this.attrs = unnull(attrs, {});
67 | return this;
68 | };
69 | FakeSVG.prototype.format = function(x, y, width) {
70 | // Virtual
71 | };
72 | FakeSVG.prototype.addTo = function(parent) {
73 | if(parent instanceof FakeSVG) {
74 | parent.children.push(this);
75 | return this;
76 | } else {
77 | var svg = this.toSVG();
78 | parent.appendChild(svg);
79 | return svg;
80 | }
81 | };
82 | FakeSVG.prototype.toSVG = function() {
83 | var el = SVG(this.tagName, this.attrs);
84 | if(typeof this.children == 'string') {
85 | el.textContent = this.children;
86 | } else {
87 | this.children.forEach(function(e) {
88 | el.appendChild(e.toSVG());
89 | });
90 | }
91 | return el;
92 | };
93 | FakeSVG.prototype.toString = function() {
94 | var str = '<' + this.tagName + ' ';
95 | for(var attr in this.attrs) {
96 | str += attr + '="' + (this.attrs[attr]+'').replace('&', '&').replace('"', '"') + '" ';
97 | }
98 | str += '>';
99 | if(typeof this.children == 'string') {
100 | str += this.children.replace('&', '&').replace('<', '<');
101 | } else {
102 | this.children.forEach(function(e) {
103 | str += e;
104 | });
105 | }
106 | str += '' + this.tagName + '>';
107 | return str;
108 | }
109 |
110 | function Path(x,y) {
111 | if(!(this instanceof Path)) return new Path(x,y);
112 | FakeSVG.call(this, 'path');
113 | this.attrs.d = "M"+x+' '+y;
114 | }
115 | subclassOf(Path, FakeSVG);
116 | Path.prototype.m = function(x,y) {
117 | this.attrs.d += 'm'+x+' '+y;
118 | return this;
119 | }
120 | Path.prototype.h = function(val) {
121 | this.attrs.d += 'h'+val;
122 | return this;
123 | }
124 | Path.prototype.right = Path.prototype.h;
125 | Path.prototype.left = function(val) { return this.h(-val); }
126 | Path.prototype.v = function(val) {
127 | this.attrs.d += 'v'+val;
128 | return this;
129 | }
130 | Path.prototype.down = Path.prototype.v;
131 | Path.prototype.up = function(val) { return this.v(-val); }
132 | Path.prototype.arc = function(sweep){
133 | var x = Diagram.ARC_RADIUS;
134 | var y = Diagram.ARC_RADIUS;
135 | if(sweep[0] == 'e' || sweep[1] == 'w') {
136 | x *= -1;
137 | }
138 | if(sweep[0] == 's' || sweep[1] == 'n') {
139 | y *= -1;
140 | }
141 | if(sweep == 'ne' || sweep == 'es' || sweep == 'sw' || sweep == 'wn') {
142 | var cw = 1;
143 | } else {
144 | var cw = 0;
145 | }
146 | this.attrs.d += "a"+Diagram.ARC_RADIUS+" "+Diagram.ARC_RADIUS+" 0 0 "+cw+' '+x+' '+y;
147 | return this;
148 | }
149 | Path.prototype.format = function() {
150 | // All paths in this library start/end horizontally.
151 | // The extra .5 ensures a minor overlap, so there's no seams in bad rasterizers.
152 | this.attrs.d += 'h.5';
153 | return this;
154 | }
155 |
156 | function Diagram(items) {
157 | if(!(this instanceof Diagram)) return new Diagram([].slice.call(arguments));
158 | FakeSVG.call(this, 'svg', {class: Diagram.DIAGRAM_CLASS});
159 | this.items = items.map(wrapString);
160 | this.items.unshift(new Start);
161 | this.items.push(new End);
162 | this.width = this.items.reduce(function(sofar, el) { return sofar + el.width + (el.needsSpace?20:0)}, 0)+1;
163 | this.up = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.up)}, 0);
164 | this.down = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.down)}, 0);
165 | this.formatted = false;
166 | }
167 | subclassOf(Diagram, FakeSVG);
168 | for(var option in options) {
169 | Diagram[option] = options[option];
170 | }
171 | Diagram.prototype.format = function(paddingt, paddingr, paddingb, paddingl) {
172 | paddingt = unnull(paddingt, 20);
173 | paddingr = unnull(paddingt, 20);
174 | paddingb = unnull(paddingt, 20);
175 | paddingl = unnull(paddingr, 20);
176 | var x = paddingl;
177 | var y = paddingt;
178 | y += this.up;
179 | var g = FakeSVG('g', Diagram.STROKE_ODD_PIXEL_LENGTH ? {transform:'translate(.5 .5)'} : {});
180 | for(var i = 0; i < this.items.length; i++) {
181 | var item = this.items[i];
182 | if(item.needsSpace) {
183 | Path(x,y).h(10).addTo(g);
184 | x += 10;
185 | }
186 | item.format(x, y, item.width).addTo(g);
187 | x += item.width;
188 | if(item.needsSpace) {
189 | Path(x,y).h(10).addTo(g);
190 | x += 10;
191 | }
192 | }
193 | this.attrs.width = this.width + paddingl + paddingr;
194 | this.attrs.height = this.up + this.down + paddingt + paddingb;
195 | g.addTo(this);
196 | this.formatted = true;
197 | return this;
198 | }
199 | Diagram.prototype.addTo = function(parent) {
200 | parent = parent || document.body;
201 | return this.$super.addTo.call(this, parent);
202 | }
203 | Diagram.prototype.toSVG = function() {
204 | if (!this.formatted) {
205 | this.format();
206 | }
207 | return this.$super.toSVG.call(this);
208 | }
209 | Diagram.prototype.toString = function() {
210 | if (!this.formatted) {
211 | this.format();
212 | }
213 | return this.$super.toString.call(this);
214 | }
215 |
216 | function Sequence(items) {
217 | if(!(this instanceof Sequence)) return new Sequence([].slice.call(arguments));
218 | FakeSVG.call(this, 'g');
219 | this.items = items.map(wrapString);
220 | this.width = this.items.reduce(function(sofar, el) { return sofar + el.width + (el.needsSpace?20:0)}, 0);
221 | this.up = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.up)}, 0);
222 | this.down = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.down)}, 0);
223 | }
224 | subclassOf(Sequence, FakeSVG);
225 | Sequence.prototype.format = function(x,y,width) {
226 | // Hook up the two sides if this is narrower than its stated width.
227 | var gaps = determineGaps(width, this.width);
228 | Path(x,y).h(gaps[0]).addTo(this);
229 | Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
230 | x += gaps[0];
231 |
232 | for(var i = 0; i < this.items.length; i++) {
233 | var item = this.items[i];
234 | if(item.needsSpace) {
235 | Path(x,y).h(10).addTo(this);
236 | x += 10;
237 | }
238 | item.format(x, y, item.width).addTo(this);
239 | x += item.width;
240 | if(item.needsSpace) {
241 | Path(x,y).h(10).addTo(this);
242 | x += 10;
243 | }
244 | }
245 | return this;
246 | }
247 |
248 | function Choice(normal, items) {
249 | if(!(this instanceof Choice)) return new Choice(normal, [].slice.call(arguments,1));
250 | FakeSVG.call(this, 'g');
251 | this.normal = normal;
252 | this.items = items.map(wrapString);
253 | this.width = this.items.reduce(function(sofar, el){return Math.max(sofar, el.width)},0) + Diagram.ARC_RADIUS*4;
254 | this.up = this.down = 0;
255 | for(var i = 0; i < this.items.length; i++) {
256 | var item = this.items[i];
257 | if(i < normal) { this.up += Math.max(Diagram.ARC_RADIUS,item.up + item.down + Diagram.VERTICAL_SEPARATION); }
258 | if(i == normal) { this.up += Math.max(Diagram.ARC_RADIUS, item.up); this.down += Math.max(Diagram.ARC_RADIUS, item.down); }
259 | if(i > normal) { this.down += Math.max(Diagram.ARC_RADIUS,Diagram.VERTICAL_SEPARATION + item.up + item.down); }
260 | }
261 | }
262 | subclassOf(Choice, FakeSVG);
263 | Choice.prototype.format = function(x,y,width) {
264 | // Hook up the two sides if this is narrower than its stated width.
265 | var gaps = determineGaps(width, this.width);
266 | Path(x,y).h(gaps[0]).addTo(this);
267 | Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
268 | x += gaps[0];
269 |
270 | var last = this.items.length -1;
271 | var innerWidth = this.width - Diagram.ARC_RADIUS*4;
272 |
273 | // Do the elements that curve above
274 | for(var i = this.normal - 1; i >= 0; i--) {
275 | var item = this.items[i];
276 | if( i == this.normal - 1 ) {
277 | var distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.items[i+1].up + Diagram.VERTICAL_SEPARATION + item.down);
278 | }
279 | Path(x,y).arc('se').up(distanceFromY - Diagram.ARC_RADIUS*2).arc('wn').addTo(this);
280 | item.format(x+Diagram.ARC_RADIUS*2,y - distanceFromY,innerWidth).addTo(this);
281 | Path(x+Diagram.ARC_RADIUS*2+innerWidth, y-distanceFromY).arc('ne').down(distanceFromY - Diagram.ARC_RADIUS*2).arc('ws').addTo(this);
282 | distanceFromY += Math.max(Diagram.ARC_RADIUS, item.up + Diagram.VERTICAL_SEPARATION + (i == 0 ? 0 : this.items[i-1].down));
283 | }
284 |
285 | // Do the straight-line path.
286 | Path(x,y).right(Diagram.ARC_RADIUS*2).addTo(this);
287 | this.items[this.normal].format(x+Diagram.ARC_RADIUS*2, y, innerWidth).addTo(this);
288 | Path(x+Diagram.ARC_RADIUS*2+innerWidth, y).right(Diagram.ARC_RADIUS*2).addTo(this);
289 |
290 | // Do the elements that curve below
291 | for(var i = this.normal+1; i <= last; i++) {
292 | var item = this.items[i];
293 | if( i == this.normal + 1 ) {
294 | var distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.items[i-1].down + Diagram.VERTICAL_SEPARATION + item.up);
295 | }
296 | Path(x,y).arc('ne').down(distanceFromY - Diagram.ARC_RADIUS*2).arc('ws').addTo(this);
297 | item.format(x+Diagram.ARC_RADIUS*2, y+distanceFromY, innerWidth).addTo(this);
298 | Path(x+Diagram.ARC_RADIUS*2+innerWidth, y+distanceFromY).arc('se').up(distanceFromY - Diagram.ARC_RADIUS*2).arc('wn').addTo(this);
299 | distanceFromY += Math.max(Diagram.ARC_RADIUS, item.down + Diagram.VERTICAL_SEPARATION + (i == last ? 0 : this.items[i+1].up));
300 | }
301 |
302 | return this;
303 | }
304 |
305 | function Optional(item, skip) {
306 | if( skip === undefined )
307 | return Choice(1, Skip(), item);
308 | else if ( skip === "skip" )
309 | return Choice(0, Skip(), item);
310 | else
311 | throw "Unknown value for Optional()'s 'skip' argument.";
312 | }
313 |
314 | function OneOrMore(item, rep) {
315 | if(!(this instanceof OneOrMore)) return new OneOrMore(item, rep);
316 | FakeSVG.call(this, 'g');
317 | rep = rep || (new Skip);
318 | this.item = wrapString(item);
319 | this.rep = wrapString(rep);
320 | this.width = Math.max(this.item.width, this.rep.width) + Diagram.ARC_RADIUS*2;
321 | this.up = this.item.up;
322 | this.down = Math.max(Diagram.ARC_RADIUS*2, this.item.down + Diagram.VERTICAL_SEPARATION + this.rep.up + this.rep.down);
323 | }
324 | subclassOf(OneOrMore, FakeSVG);
325 | OneOrMore.prototype.needsSpace = true;
326 | OneOrMore.prototype.format = function(x,y,width) {
327 | // Hook up the two sides if this is narrower than its stated width.
328 | var gaps = determineGaps(width, this.width);
329 | Path(x,y).h(gaps[0]).addTo(this);
330 | Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
331 | x += gaps[0];
332 |
333 | // Draw item
334 | Path(x,y).right(Diagram.ARC_RADIUS).addTo(this);
335 | this.item.format(x+Diagram.ARC_RADIUS,y,this.width-Diagram.ARC_RADIUS*2).addTo(this);
336 | Path(x+this.width-Diagram.ARC_RADIUS,y).right(Diagram.ARC_RADIUS).addTo(this);
337 |
338 | // Draw repeat arc
339 | var distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.item.down+Diagram.VERTICAL_SEPARATION+this.rep.up);
340 | Path(x+Diagram.ARC_RADIUS,y).arc('nw').down(distanceFromY-Diagram.ARC_RADIUS*2).arc('ws').addTo(this);
341 | this.rep.format(x+Diagram.ARC_RADIUS, y+distanceFromY, this.width - Diagram.ARC_RADIUS*2).addTo(this);
342 | Path(x+this.width-Diagram.ARC_RADIUS, y+distanceFromY).arc('se').up(distanceFromY-Diagram.ARC_RADIUS*2).arc('en').addTo(this);
343 |
344 | return this;
345 | }
346 |
347 | function ZeroOrMore(item, rep, skip) {
348 | return Optional(OneOrMore(item, rep), skip);
349 | }
350 |
351 | function Start() {
352 | if(!(this instanceof Start)) return new Start();
353 | FakeSVG.call(this, 'path');
354 | this.width = 20;
355 | this.up = 10;
356 | this.down = 10;
357 | }
358 | subclassOf(Start, FakeSVG);
359 | Start.prototype.format = function(x,y) {
360 | this.attrs.d = 'M '+x+' '+(y-10)+' v 20 m 10 -20 v 20 m -10 -10 h 20.5';
361 | return this;
362 | }
363 |
364 | function End() {
365 | if(!(this instanceof End)) return new End();
366 | FakeSVG.call(this, 'path');
367 | this.width = 20;
368 | this.up = 10;
369 | this.down = 10;
370 | }
371 | subclassOf(End, FakeSVG);
372 | End.prototype.format = function(x,y) {
373 | this.attrs.d = 'M '+x+' '+y+' h 20 m -10 -10 v 20 m 10 -20 v 20';
374 | return this;
375 | }
376 |
377 | function Terminal(text) {
378 | if(!(this instanceof Terminal)) return new Terminal(text);
379 | FakeSVG.call(this, 'g');
380 | this.text = text;
381 | this.width = text.length * 8 + 20; /* Assume that each char is .5em, and that the em is 16px */
382 | this.up = 11;
383 | this.down = 11;
384 | }
385 | subclassOf(Terminal, FakeSVG);
386 | Terminal.prototype.needsSpace = true;
387 | Terminal.prototype.format = function(x, y, width) {
388 | // Hook up the two sides if this is narrower than its stated width.
389 | var gaps = determineGaps(width, this.width);
390 | Path(x,y).h(gaps[0]).addTo(this);
391 | Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
392 | x += gaps[0];
393 |
394 | FakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down, rx:10, ry:10}).addTo(this);
395 | FakeSVG('text', {x:x+this.width/2, y:y+4}, this.text).addTo(this);
396 | return this;
397 | }
398 |
399 | function NonTerminal(text) {
400 | if(!(this instanceof NonTerminal)) return new NonTerminal(text);
401 | FakeSVG.call(this, 'g');
402 | this.text = text;
403 | this.width = text.length * 8 + 20;
404 | this.up = 11;
405 | this.down = 11;
406 | }
407 | subclassOf(NonTerminal, FakeSVG);
408 | NonTerminal.prototype.needsSpace = true;
409 | NonTerminal.prototype.format = function(x, y, width) {
410 | // Hook up the two sides if this is narrower than its stated width.
411 | var gaps = determineGaps(width, this.width);
412 | Path(x,y).h(gaps[0]).addTo(this);
413 | Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
414 | x += gaps[0];
415 |
416 | FakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down}).addTo(this);
417 | FakeSVG('text', {x:x+this.width/2, y:y+4}, this.text).addTo(this);
418 | return this;
419 | }
420 |
421 | function Comment(text) {
422 | if(!(this instanceof Comment)) return new Comment(text);
423 | FakeSVG.call(this, 'g');
424 | this.text = text;
425 | this.width = text.length * 7 + 10;
426 | this.up = 11;
427 | this.down = 11;
428 | }
429 | subclassOf(Comment, FakeSVG);
430 | Comment.prototype.needsSpace = true;
431 | Comment.prototype.format = function(x, y, width) {
432 | // Hook up the two sides if this is narrower than its stated width.
433 | var gaps = determineGaps(width, this.width);
434 | Path(x,y).h(gaps[0]).addTo(this);
435 | Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this);
436 | x += gaps[0];
437 |
438 | FakeSVG('text', {x:x+this.width/2, y:y+5, class:'comment'}, this.text).addTo(this);
439 | return this;
440 | }
441 |
442 | function Skip() {
443 | if(!(this instanceof Skip)) return new Skip();
444 | FakeSVG.call(this, 'g');
445 | this.width = 0;
446 | this.up = 0;
447 | this.down = 0;
448 | }
449 | subclassOf(Skip, FakeSVG);
450 | Skip.prototype.format = function(x, y, width) {
451 | Path(x,y).right(width).addTo(this);
452 | return this;
453 | }
454 |
455 | return [Diagram, Sequence, Choice, Optional, OneOrMore, ZeroOrMore, Terminal, NonTerminal, Comment, Skip]
456 | })(
457 | {
458 | VERTICAL_SEPARATION: 8,
459 | ARC_RADIUS: 10,
460 | DIAGRAM_CLASS: 'railroad-diagram',
461 | STROKE_ODD_PIXEL_LENGTH: true,
462 | INTERNAL_ALIGNMENT: 'center',
463 | }
464 | );
465 |
466 | /*
467 | These are the names that the internal classes are exported as.
468 | If you would like different names, adjust them here.
469 | */
470 | ['Diagram', 'Sequence', 'Choice', 'Optional', 'OneOrMore', 'ZeroOrMore', 'Terminal', 'NonTerminal', 'Comment', 'Skip']
471 | .forEach(function(e,i) { window[e] = temp[i]; });
--------------------------------------------------------------------------------
/doc/sample.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
21 |
22 |
23 | public |
24 | _ private |
25 | pr protected |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/doc/screen1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ulex/ZenSharp/6ffb45b8c817e463be8bd24d822eed87a9844f00/doc/screen1.gif
--------------------------------------------------------------------------------
/doc/screen2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ulex/ZenSharp/6ffb45b8c817e463be8bd24d822eed87a9844f00/doc/screen2.gif
--------------------------------------------------------------------------------
/patchAssemblyInfo.ps1:
--------------------------------------------------------------------------------
1 | # copyright: http://blogs.msdn.com/b/dotnetinterop/archive/2008/04/21/powershell-script-to-batch-update-assemblyinfo-cs-with-new-version.aspx
2 | # added support to Nemerle Assembly infos
3 | # SetVersion.ps1
4 | #
5 | # Set the version in all the AssemblyInfo.cs or AssemblyInfo.vb files in any subdirectory.
6 | #
7 | # usage:
8 | # from cmd.exe:
9 | # powershell.exe SetVersion.ps1 2.8.3.0
10 | #
11 | # from powershell.exe prompt:
12 | # .\SetVersion.ps1 2.8.3.0
13 | #
14 | # last saved Time-stamp:
15 | #
16 |
17 |
18 | function Usage
19 | {
20 | echo "Usage: ";
21 | echo " from cmd.exe: ";
22 | echo " powershell.exe SetVersion.ps1 2.8.3.0";
23 | echo " ";
24 | echo " from powershell.exe prompt: ";
25 | echo " .\SetVersion.ps1 2.8.3.0";
26 | echo " ";
27 | }
28 |
29 |
30 | function Update-SourceVersion
31 | {
32 | Param ([string]$Version)
33 | $NewVersion = 'AssemblyVersion("' + $Version + '")';
34 | $NewFileVersion = 'AssemblyFileVersion("' + $Version + '")';
35 |
36 | foreach ($o in $input)
37 | {
38 | Write-output $o.FullName
39 | $TmpFile = $o.FullName + ".tmp"
40 |
41 | get-content $o.FullName |
42 | %{$_ -replace 'AssemblyVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)', $NewVersion } |
43 | %{$_ -replace 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)', $NewFileVersion } |
44 | Set-Content -Encoding UTF8 $TmpFile
45 |
46 | move-item $TmpFile $o.FullName -force
47 | }
48 | }
49 |
50 |
51 | function Update-AllAssemblyInfoFiles ( $version )
52 | {
53 | foreach ($file in "AssemblyInfo.cs", "AssemblyInfo.n" )
54 | {
55 | get-childitem -recurse |? {$_.Name -eq $file} | Update-SourceVersion $version ;
56 | }
57 | }
58 |
59 |
60 | Update-AllAssemblyInfoFiles $args[0];
61 |
--------------------------------------------------------------------------------