1
+
using Signum.Utilities;
2
+
using System;
3
+
using System.Collections.Generic;
4
+
using System.IO;
5
+
using System.Linq;
6
+
using System.Text;
7
+
using System.Text.RegularExpressions;
8
+
9
+
namespace Signum.Engine.CodeGeneration
10
+
{
11
+
public class ReactHookConverter
12
+
{
13
+
public void ConvertFilesToHooks()
14
+
{
15
+
while (true)
16
+
{
17
+
IEnumerable<string> files = GetFiles();
18
+
19
+
if (files == null)
20
+
return;
21
+
22
+
foreach (var file in files)
23
+
{
24
+
Console.Write(file + "...");
25
+
26
+
var content = File.ReadAllText(file);
27
+
28
+
var converted = SimplifyFile(content);
29
+
30
+
File.WriteAllText(file, converted);
31
+
}
32
+
}
33
+
}
34
+
35
+
public virtual IEnumerable<string> GetFiles()
36
+
{
37
+
string folder = GetFolder();
38
+
39
+
var files = Directory.EnumerateFiles(folder, "*.tsx", SearchOption.AllDirectories);
40
+
41
+
return SelectFiles(folder, files);
42
+
}
43
+
44
+
public virtual string GetFolder()
45
+
{
46
+
CodeGenerator.GetSolutionInfo(out var solutionFolder, out var solutionName);
47
+
48
+
var folder = $@"{solutionFolder}\{solutionName}.React\App";
49
+
return folder;
50
+
}
51
+
52
+
public virtual IEnumerable<string> SelectFiles(string folder, IEnumerable<string> files)
53
+
{
54
+
var result = files.Select(a => a.After(folder)).ChooseConsoleMultiple();
55
+
56
+
if (result.IsEmpty())
57
+
return null;
58
+
59
+
return result.Select(a => folder + a);
60
+
}
61
+
62
+
public virtual string SimplifyFile(string content)
63
+
{
64
+
HashSet<string> hookImports = new HashSet<string>();
65
+
66
+
67
+
var componentStarts = Regex.Matches(content, @"^(?<export>export )?(?<default>default )?class (?<className>\w+) extends React\.Component<(?<props>.*?)>\s*{\s*\r\n", RegexOptions.Multiline).Cast<Match>();
68
+
69
+
foreach (var m in componentStarts.Reverse())
70
+
{
71
+
var endMatch = new Regex(@"^}\s*$", RegexOptions.Multiline).Match(content, m.EndIndex());
72
+
73
+
var simplifiedContent = SimplifyClass(content.Substring(m.EndIndex(), endMatch.Index - m.EndIndex()), hookImports);
74
+
75
+
string newComponent = m.Groups["export"].Value + m.Groups["default"].Value + "function " + m.Groups["className"].Value + "(p : " + m.Groups["props"].Value + "){\r\n"
76
+
+ simplifiedContent
77
+
+ endMatch.Value;
78
+
79
+
80
+
content = content.Substring(0, m.Index) + newComponent + content.Substring(endMatch.EndIndex());
81
+
}
82
+
83
+
84
+
if (hookImports.Any())
85
+
{
86
+
var lastImport = Regex.Matches(content, "^import.*\r\n", RegexOptions.Multiline).Cast<Match>().Last();
87
+
88
+
return content.Substring(0, lastImport.EndIndex()) +
89
+
$"import {{ {hookImports.ToString(", ")} }} from '@framework/Hooks'\r\n" +
90
+
content.Substring(lastImport.EndIndex());
91
+
}
92
+
else
93
+
{
94
+
95
+
return content;
96
+
}
97
+
}
98
+
99
+
public virtual string SimplifyClass(string content, HashSet<string> hookImports)
100
+
{
101
+
HashSet<string> hooks = new HashSet<string>();
102
+
103
+
var matches = Regex.Matches(content, @"^ (?<text>\w.+)\s*\r\n", RegexOptions.Multiline).Cast<Match>().ToList();
104
+
var endMatch = new Regex(@"^ };?\s*$", RegexOptions.Multiline).Matches(content).Cast<Match>().ToList();
105
+
106
+
var pairs = matches.Select(m => new { isStart = true, m })
107
+
.Concat(endMatch.Select(m => new { isStart = false, m }))
108
+
.OrderBy(p => p.m.Index)
109
+
.BiSelect((start, end) => new { start, end })
110
+
.Where(a => a.start.isStart && !a.end.isStart)
111
+
.Select(a => new { start = a.start.m, end = a.end.m })
112
+
.ToList();
113
+
114
+
string render = null;
115
+
116
+
foreach (var p in pairs.AsEnumerable().Reverse())
117
+
{
118
+
var methodContent = content.Substring(p.start.EndIndex(), p.end.Index - p.start.EndIndex());
119
+
120
+
var simplifiedContent = SimplifyMethod(methodContent, hooks, hookImports);
121
+
122
+
if (p.start.Value.Contains("render()"))
123
+
{
124
+
render = simplifiedContent.Lines().Select(l => l.StartsWith(" ") ? l.Substring(2) : l).ToString("\r\n");
125
+
126
+
content = content.Substring(0, p.start.Index) + content.Substring(p.end.EndIndex());
127
+
}
128
+
else
129
+
{
130
+
string newComponent = ConvertToFunction(p.start.Value) + simplifiedContent + p.end.Value;
131
+
132
+
content = content.Substring(0, p.start.Index) + newComponent + content.Substring(p.end.EndIndex());
133
+
}
134
+
}
135
+
136
+
return hooks.ToString(s => s + ";\r\n", "").Indent(2) + content + render;
137
+
138
+
}
139
+
140
+
public virtual string ConvertToFunction(string value)
141
+
{
142
+
{
143
+
var lambda = Regex.Match(value, @"(?<ident> *)(?<name>\w+) *= *\((?<params>.*)\) *=> *{");
144
+
if (lambda.Success)
145
+
return $"{lambda.Groups["ident"].Value}function {lambda.Groups["name"].Value}({lambda.Groups["params"].Value}) {{\r\n";
146
+
}
147
+
148
+
{
149
+
var method = Regex.Match(value, @"(?<ident> *)(?<name>\w+) *\((?<params>.*)\) *{");
150
+
if (method.Success)
151
+
return $"{method.Groups["ident"].Value}function {method.Groups["name"].Value}({method.Groups["params"].Value}) {{\r\n";
152
+
}
153
+
return value;
154
+
}
155
+
156
+
public virtual string SimplifyMethod(string methodBody, HashSet<string> hooks, HashSet<string> hooksImports)
157
+
{
158
+
methodBody = methodBody.Replace("this.props", "p");
159
+
160
+
if(methodBody.Contains("this.forceUpdate"))
161
+
{
162
+
hooksImports.Add("useForceUpdate");
163
+
hooks.Add("const forceUpdate = useForceUpdate()");
164
+
methodBody = methodBody.Replace("this.forceUpdate", "forceUpdate");
165
+
}
166
+
methodBody = methodBody.Replace("this.state.", "");
167
+
methodBody = methodBody.Replace("this.", "");
168
+
169
+
return methodBody;
170
+
}
171
+
}
172
+
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4