Skip to content

Commit d646dcf

Browse files
committed
Added method "GenerateOneContinuously":
generating continuously by watching the cs file. Added option " UseStrictEquality": replace '<c>==</c>' with '<c>===</c>' default false. Initial support dictionary to map. Small changes, bug fixes.
1 parent db2c5c8 commit d646dcf

File tree

3 files changed

+190
-50
lines changed

3 files changed

+190
-50
lines changed

CSharpToJavaScript/CSTOJS.cs

Lines changed: 107 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ public class CSTOJS : ILog
2626
private readonly Stopwatch _Stopwatch = new();
2727

2828
private Walker? _Walker = null;
29+
private FileSystemWatcher? _FSWatcher = null;
2930

3031
/// <summary>
3132
/// New instance of <see cref="CSTOJS"/> with default options, see <see cref="CSTOJSOptions"/>.
3233
/// </summary>
33-
public CSTOJS()
34+
public CSTOJS()
3435
{
3536
_Log = ILog.GetILog(this, _Options);
3637

@@ -64,7 +65,7 @@ public CSTOJS(CSTOJSOptions options)
6465
/// <param name="filename">Optional! Filename of a js file if you generating one file!</param>
6566
/// <returns>empty Task</returns>
6667
/// <exception cref="DirectoryNotFoundException"></exception>
67-
public async Task GenerateOneAsync(string path, string? filename = null)
68+
public async Task GenerateOneAsync(string path, string? filename = null)
6869
{
6970
Assembly? assembly = Assembly.GetEntryAssembly();
7071
List<FileInfo> files = new();
@@ -73,7 +74,7 @@ public async Task GenerateOneAsync(string path, string? filename = null)
7374
{
7475
files.Add(new FileInfo(path));
7576
}
76-
else
77+
else
7778
{
7879
if (!Directory.Exists(path))
7980
throw new DirectoryNotFoundException(path);
@@ -89,7 +90,7 @@ public async Task GenerateOneAsync(string path, string? filename = null)
8990
{
9091
SyntaxTree? _tree = null;
9192

92-
using (var stream = File.OpenRead(file.FullName))
93+
using (var stream = File.Open(file.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
9394
{
9495
_tree = CSharpSyntaxTree.ParseText(SourceText.From(stream), path: file.FullName);
9596
}
@@ -171,15 +172,15 @@ public List<StringBuilder> GenerateOne(string path)
171172
/// <param name="references">Needed if you don't have access to files. Because Assembly.location is null in Blazor WebAssembly.</param>
172173
/// <returns>JS <see cref="StringBuilder"/></returns>
173174
/// <exception cref="ArgumentNullException"></exception>
174-
public StringBuilder GenerateOneFromString(string csstring, List<MetadataReference>? references = null)
175+
public StringBuilder GenerateOneFromString(string csstring, List<MetadataReference>? references = null)
175176
{
176177
ArgumentNullException.ThrowIfNull(csstring);
177178

178179
Assembly? assembly = Assembly.GetEntryAssembly();
179180

180181
SyntaxTree _tree = CSharpSyntaxTree.ParseText(csstring);
181-
182-
if(references != null)
182+
183+
if (references != null)
183184
Generate(_tree, assembly, references);
184185
else
185186
Generate(_tree, assembly);
@@ -218,18 +219,100 @@ public async Task GenerateOneFromStringAsync(string csstring, string? filename =
218219
}
219220

220221
string pathCombined = Path.Combine(_Options.OutPutPath, filename);
221-
222+
222223
await File.WriteAllTextAsync(pathCombined, _Walker.JSSB.ToString());
223224

224225
_Log.SuccessLine($"--- Done!");
225226
_Log.SuccessLine($"--- Path: {pathCombined}");
226227
_Log.SuccessLine($"--- --- ---");
227228
}
228229

230+
/// <summary>
231+
/// Method for generating continuously by watching the cs file. Writes a file.
232+
/// </summary>
233+
/// <remarks>
234+
/// <blockquote class="NOTE"><h5>NOTE</h5><para>Note: You must call <see cref="CSTOJS.StopWatching" /> before completing a program.</para></blockquote>
235+
/// </remarks>
236+
/// <param name="path">Full path to cs file.</param>
237+
/// <returns>void</returns>
238+
/// <exception cref="DirectoryNotFoundException"></exception>
239+
/// <exception cref="FileNotFoundException"></exception>
240+
public void GenerateOneContinuously(string path)
241+
{
242+
if (File.Exists(path))
243+
{
244+
FileInfo file = new(path);
245+
246+
if(file.Directory == null)
247+
throw new DirectoryNotFoundException(path);
248+
249+
_FSWatcher = new(file.Directory.FullName);
250+
251+
_FSWatcher.NotifyFilter = NotifyFilters.LastWrite;
252+
253+
_FSWatcher.Changed += OnChanged;
254+
_FSWatcher.Created += OnCreated;
255+
_FSWatcher.Deleted += OnDeleted;
256+
_FSWatcher.Renamed += OnRenamed;
257+
_FSWatcher.Error += OnError;
258+
259+
_FSWatcher.Filter = file.Name;
260+
_FSWatcher.IncludeSubdirectories = true;
261+
_FSWatcher.EnableRaisingEvents = true;
262+
}
263+
else
264+
{
265+
throw new FileNotFoundException(path);
266+
}
267+
}
268+
private async void OnChanged(object sender, FileSystemEventArgs e)
269+
{
270+
if (e.ChangeType != WatcherChangeTypes.Changed)
271+
return;
272+
273+
_Log.WriteLine($"Changed: {e.FullPath}");
274+
275+
await GenerateOneAsync(e.FullPath);
276+
}
277+
278+
private void OnCreated(object sender, FileSystemEventArgs e)
279+
{
280+
string value = $"Created: {e.FullPath}";
281+
_Log.WriteLine(value);
282+
}
283+
284+
private void OnDeleted(object sender, FileSystemEventArgs e)
285+
{
286+
_Log.WriteLine($"Deleted: {e.FullPath}");
287+
}
288+
289+
private void OnRenamed(object sender, RenamedEventArgs e)
290+
{
291+
_Log.WriteLine($"Renamed:");
292+
_Log.WriteLine($" Old: {e.OldFullPath}");
293+
_Log.WriteLine($" New: {e.FullPath}");
294+
}
295+
296+
private void OnError(object sender, ErrorEventArgs e)
297+
{
298+
throw e.GetException();
299+
}
300+
301+
/// <summary>
302+
/// Method for stopping watching cs file.
303+
/// </summary>
304+
public void StopWatching()
305+
{
306+
if (_FSWatcher != null)
307+
{
308+
_FSWatcher.Dispose();
309+
_FSWatcher = null;
310+
}
311+
}
229312

230-
private void Generate(SyntaxTree tree, Assembly? assembly, List<MetadataReference>? refs = null)
313+
private void Generate(SyntaxTree tree, Assembly? assembly, List<MetadataReference>? refs = null)
231314
{
232-
if(_Options.Debug)
315+
if (_Options.Debug)
233316
{
234317
_Stopwatch.Restart();
235318
_Log.WriteLine("Start stopwatch");
@@ -262,7 +345,7 @@ private void Generate(SyntaxTree tree, Assembly? assembly, List<MetadataReferenc
262345
}
263346
}
264347
}
265-
else
348+
else
266349
{
267350
references = refs;
268351
}
@@ -428,38 +511,23 @@ private void Generate(SyntaxTree tree, Assembly? assembly, List<MetadataReferenc
428511

429512
if (_Options.KeepBraceOnTheSameLine)
430513
{
431-
//
432-
//
433-
//Overriding root works only once.
434-
//ReplaceTokens? how?
435-
//I'm not sure how to properly fix this...
436-
//Below is a very bad code...
437-
//
438-
//Todo! Delete 'tab' before 'EndOfLineTrivia', if there is any.
439-
//Also cant figure out how to use ReplaceTokens...
440-
//https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.syntaxnodeextensions.replacetokens?view=roslyn-dotnet-4.9.0
514+
//TODO! remove whitespace trivia before brace!
441515
List<SyntaxToken> allBraces = trueRoot.DescendantTokens().Where((e) => e.IsKind(SyntaxKind.OpenBraceToken)).ToList();
442-
int i = 0;
443-
while (i < allBraces.Count)
516+
List<SyntaxTrivia> allTriviaToReplace = new();
517+
for (int i = 0; i < allBraces.Count; i++)
444518
{
445-
for (int j = 0; j < allBraces.Count; j++)
519+
SyntaxToken _token = allBraces[i].GetPreviousToken();
520+
if (_token.HasTrailingTrivia)
446521
{
447-
SyntaxToken _token = allBraces[j].GetPreviousToken();
448-
if (_token.HasTrailingTrivia)
522+
SyntaxTrivia _trivia = _token.TrailingTrivia.Where((e) => e.IsKind(SyntaxKind.EndOfLineTrivia)).FirstOrDefault();
523+
if (!_trivia.IsKind(SyntaxKind.None))
449524
{
450-
SyntaxTrivia _trivia = _token.TrailingTrivia.Where((e) => e.IsKind(SyntaxKind.EndOfLineTrivia)).FirstOrDefault();
451-
if (!_trivia.IsKind(SyntaxKind.None))
452-
{
453-
SyntaxToken _replacedToken = _token.ReplaceTrivia(_trivia, SyntaxFactory.Space);
454-
trueRoot = trueRoot.ReplaceToken(_token, _replacedToken);
455-
break;
456-
}
525+
allTriviaToReplace.Add(_trivia);
457526
}
458527
}
459-
allBraces = trueRoot.DescendantTokens().Where((e) => e.IsKind(SyntaxKind.OpenBraceToken)).ToList();
460-
i++;
461528
}
462-
529+
trueRoot = trueRoot.ReplaceTrivia(allTriviaToReplace, (o, r) => SyntaxFactory.Space);
530+
463531
}
464532

465533
if (rtPath != null && rtPath != string.Empty)
@@ -484,7 +552,7 @@ private void Generate(SyntaxTree tree, Assembly? assembly, List<MetadataReferenc
484552

485553
if (File.Exists(Path.Combine(rtPath, "System.Threading.Tasks.dll")))
486554
references.Add(MetadataReference.CreateFromFile(Path.Combine(rtPath, "System.Threading.Tasks.dll")));
487-
555+
488556
if (File.Exists(Path.Combine(rtPath, "System.Console.dll")))
489557
references.Add(MetadataReference.CreateFromFile(Path.Combine(rtPath, "System.Console.dll")));
490558

@@ -513,7 +581,7 @@ private void Generate(SyntaxTree tree, Assembly? assembly, List<MetadataReferenc
513581
if (item.Display == null)
514582
continue;
515583

516-
if (resultItem.Display == item.Display)
584+
if (resultItem.Display == item.Display)
517585
found = true;
518586
}
519587

@@ -547,7 +615,7 @@ private void Generate(SyntaxTree tree, Assembly? assembly, List<MetadataReferenc
547615
.AddReferences(trueReferences.ToArray())
548616
.AddSyntaxTrees(trueST);
549617

550-
618+
551619
_Walker = new(_Options, compilation.GetSemanticModel(trueST));
552620

553621
_Walker.JSSB.Append(_Options.AddSBInFront);

CSharpToJavaScript/CSTOJSOptions.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public record class CSTOJSOptions
4545
public string OutPutPath { get; set; } = Directory.GetCurrentDirectory();
4646

4747
/// <summary>
48-
/// Self-explanatory, Use var over let.
48+
/// Self-explanatory, Use <c>var</c> over <c>let</c>.
4949
/// </summary>
5050
/// <value>
5151
/// Default: <c>false</c>
@@ -74,6 +74,14 @@ public record class CSTOJSOptions
7474
/// </value>
7575
public bool NormalizeWhitespace { get; set; } = false;
7676

77+
/// <summary>
78+
/// Replace '<c>==</c>' with '<c>===</c>'.
79+
/// </summary>
80+
/// <value>
81+
/// Default: <c>false</c>
82+
/// </value>
83+
public bool UseStrictEquality { get; set; } = false;
84+
7785
/// <summary>
7886
/// List of custom names to convert.
7987
/// </summary>

0 commit comments

Comments
 (0)