Skip to content

Commit 5d91082

Browse files
committed
feat: Add try-catch blocks and error logging
1 parent 4c39a43 commit 5d91082

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2549
-1479
lines changed

WorkspaceLauncherForVSCode/Classes/Constant.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Modifications copyright (c) 2025 tanchekwei
22
// Licensed under the MIT License. See the LICENSE file in the project root for details.
3-
43
using Microsoft.CommandPalette.Extensions.Toolkit;
54

65
namespace WorkspaceLauncherForVSCode.Classes;
Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Linq;
34
using WorkspaceLauncherForVSCode.Enums;
@@ -6,53 +7,87 @@ namespace WorkspaceLauncherForVSCode.Classes;
67

78
public class CountTracker
89
{
9-
private readonly Dictionary<CountType, int> _counts = new();
10-
private readonly Dictionary<VisualStudioCodeRemoteType, int> _vscodeRemoteCounts = new();
11-
private readonly Dictionary<WorkspaceType, int> _vscodeLocalCounts = new();
12-
public int this[CountType type] => _counts.TryGetValue(type, out var count) ? count : 0;
13-
public int this[VisualStudioCodeRemoteType remoteType] => _vscodeRemoteCounts.TryGetValue(remoteType, out var count) ? count : 0;
14-
public int this[WorkspaceType localType] => _vscodeLocalCounts.TryGetValue(localType, out var count) ? count : 0;
15-
16-
public void Update(CountType type, int value)
17-
{
18-
if (!_counts.TryGetValue(type, out var oldValue) || oldValue != value)
10+
private readonly Dictionary<CountType, int> _counts = new();
11+
private readonly Dictionary<VisualStudioCodeRemoteType, int> _vscodeRemoteCounts = new();
12+
private readonly Dictionary<WorkspaceType, int> _vscodeLocalCounts = new();
13+
public int this[CountType type] => _counts.TryGetValue(type, out var count) ? count : 0;
14+
public int this[VisualStudioCodeRemoteType remoteType] => _vscodeRemoteCounts.TryGetValue(remoteType, out var count) ? count : 0;
15+
public int this[WorkspaceType localType] => _vscodeLocalCounts.TryGetValue(localType, out var count) ? count : 0;
16+
17+
public void Update(CountType type, int value)
1918
{
20-
_counts[type] = value;
19+
try
20+
{
21+
if (!_counts.TryGetValue(type, out var oldValue) || oldValue != value)
22+
{
23+
_counts[type] = value;
24+
}
25+
}
26+
catch (Exception ex)
27+
{
28+
ErrorLogger.LogError(ex);
29+
}
2130
}
22-
}
23-
24-
public void Increment(CountType type)
25-
{
26-
_counts.TryGetValue(type, out var value); _counts[type] = value + 1;
27-
}
28-
29-
public void Increment(VisualStudioCodeRemoteType remoteType)
30-
{
31-
_vscodeRemoteCounts.TryGetValue(remoteType, out var value);
32-
_vscodeRemoteCounts[remoteType] = value + 1;
33-
34-
}
3531

36-
public void Increment(WorkspaceType localType)
37-
{
38-
_vscodeLocalCounts.TryGetValue(localType, out var value); _vscodeLocalCounts[localType] = value + 1;
39-
}
32+
public void Increment(CountType type)
33+
{
34+
try
35+
{
36+
_counts.TryGetValue(type, out var value); _counts[type] = value + 1;
37+
}
38+
catch (Exception ex)
39+
{
40+
ErrorLogger.LogError(ex);
41+
}
42+
}
4043

41-
public void Reset()
42-
{
43-
foreach (var key in _counts.Keys.ToList())
44+
public void Increment(VisualStudioCodeRemoteType remoteType)
4445
{
45-
_counts[key] = 0;
46+
try
47+
{
48+
_vscodeRemoteCounts.TryGetValue(remoteType, out var value);
49+
_vscodeRemoteCounts[remoteType] = value + 1;
50+
}
51+
catch (Exception ex)
52+
{
53+
ErrorLogger.LogError(ex);
54+
}
4655
}
4756

48-
foreach (var key in _vscodeRemoteCounts.Keys.ToList())
57+
public void Increment(WorkspaceType localType)
4958
{
50-
_vscodeRemoteCounts[key] = 0;
59+
try
60+
{
61+
_vscodeLocalCounts.TryGetValue(localType, out var value); _vscodeLocalCounts[localType] = value + 1;
62+
}
63+
catch (Exception ex)
64+
{
65+
ErrorLogger.LogError(ex);
66+
}
5167
}
5268

53-
foreach (var key in _vscodeLocalCounts.Keys.ToList())
69+
public void Reset()
5470
{
55-
_vscodeLocalCounts[key] = 0;
71+
try
72+
{
73+
foreach (var key in _counts.Keys.ToList())
74+
{
75+
_counts[key] = 0;
76+
}
77+
78+
foreach (var key in _vscodeRemoteCounts.Keys.ToList())
79+
{
80+
_vscodeRemoteCounts[key] = 0;
81+
}
82+
83+
foreach (var key in _vscodeLocalCounts.Keys.ToList())
84+
{
85+
_vscodeLocalCounts[key] = 0;
86+
}
87+
}
88+
catch (Exception ex)
89+
{
90+
ErrorLogger.LogError(ex);
91+
}
5692
}
57-
}
5893
}

WorkspaceLauncherForVSCode/Classes/DatabaseInitializer.cs

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// Modifications copyright (c) 2025 tanchekwei
22
// Licensed under the MIT License. See the LICENSE file in the project root for details.
3-
using Microsoft.Data.Sqlite;
3+
using System;
44
using System.Collections.Generic;
55
using System.IO;
6+
using Microsoft.Data.Sqlite;
67

78
namespace WorkspaceLauncherForVSCode.Classes
89
{
@@ -13,51 +14,58 @@ public static class VscdbRecentListChangeTrackerInitializer
1314

1415
public static void Initialize(string vscdbPath)
1516
{
16-
lock (_lock)
17+
try
1718
{
18-
if (_initializedDbs.Contains(vscdbPath))
19+
lock (_lock)
1920
{
20-
return;
21-
}
21+
if (_initializedDbs.Contains(vscdbPath))
22+
{
23+
return;
24+
}
2225

23-
using (var connection = new SqliteConnection($"Data Source={vscdbPath}"))
24-
{
25-
connection.Open();
26+
using (var connection = new SqliteConnection($"Data Source={vscdbPath}"))
27+
{
28+
connection.Open();
2629

27-
// Create the tracker table if it doesn't exist
28-
var createTableCommand = connection.CreateCommand();
29-
createTableCommand.CommandText = @"
30-
CREATE TABLE IF NOT EXISTS CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTracker (
31-
version INTEGER NOT NULL
32-
);
33-
";
34-
createTableCommand.ExecuteNonQuery();
30+
// Create the tracker table if it doesn't exist
31+
var createTableCommand = connection.CreateCommand();
32+
createTableCommand.CommandText = @"
33+
CREATE TABLE IF NOT EXISTS CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTracker (
34+
version INTEGER NOT NULL
35+
);
36+
";
37+
createTableCommand.ExecuteNonQuery();
3538

36-
// Insert a default value if the table is empty
37-
var insertCommand = connection.CreateCommand();
38-
insertCommand.CommandText = @"
39-
INSERT INTO CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTracker (version)
40-
SELECT 1
41-
WHERE NOT EXISTS (
42-
SELECT 1 FROM CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTracker
43-
);
44-
";
45-
insertCommand.ExecuteNonQuery();
39+
// Insert a default value if the table is empty
40+
var insertCommand = connection.CreateCommand();
41+
insertCommand.CommandText = @"
42+
INSERT INTO CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTracker (version)
43+
SELECT 1
44+
WHERE NOT EXISTS (
45+
SELECT 1 FROM CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTracker
46+
);
47+
";
48+
insertCommand.ExecuteNonQuery();
4649

47-
// Create the trigger to update the tracker table
48-
var triggerCommand = connection.CreateCommand();
49-
triggerCommand.CommandText = @"
50-
CREATE TRIGGER IF NOT EXISTS CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTrigger
51-
AFTER INSERT ON ItemTable
52-
WHEN NEW.key = 'history.recentlyOpenedPathsList'
53-
BEGIN
54-
UPDATE CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTracker SET version = version + 1;
55-
END;
56-
";
57-
triggerCommand.ExecuteNonQuery();
58-
}
50+
// Create the trigger to update the tracker table
51+
var triggerCommand = connection.CreateCommand();
52+
triggerCommand.CommandText = @"
53+
CREATE TRIGGER IF NOT EXISTS CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTrigger
54+
AFTER INSERT ON ItemTable
55+
WHEN NEW.key = 'history.recentlyOpenedPathsList'
56+
BEGIN
57+
UPDATE CmdPalVisualStudioCodeHistoryRecentlyOpenedPathsListTracker SET version = version + 1;
58+
END;
59+
";
60+
triggerCommand.ExecuteNonQuery();
61+
}
5962

60-
_initializedDbs.Add(vscdbPath);
63+
_initializedDbs.Add(vscdbPath);
64+
}
65+
}
66+
catch (Exception ex)
67+
{
68+
ErrorLogger.LogError(ex);
6169
}
6270
}
6371
}
Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
1-
21
using System;
32
using Microsoft.Extensions.DependencyInjection;
43

54
namespace WorkspaceLauncherForVSCode.Classes;
5+
66
public class Dependencies
77
{
8-
public IServiceProvider Services { get; }
8+
public IServiceProvider Services { get; }
99

10-
public Dependencies(IServiceProvider services)
11-
{
12-
Services = services;
13-
}
10+
public Dependencies(IServiceProvider services)
11+
{
12+
try
13+
{
14+
Services = services;
15+
}
16+
catch (Exception ex)
17+
{
18+
ErrorLogger.LogError(ex);
19+
throw;
20+
}
21+
}
1422

15-
public T Get<T>() where T : notnull => Services.GetRequiredService<T>();
23+
public T Get<T>() where T : notnull
24+
{
25+
try
26+
{
27+
return Services.GetRequiredService<T>();
28+
}
29+
catch (Exception ex)
30+
{
31+
ErrorLogger.LogError(ex);
32+
throw;
33+
}
34+
}
1635
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Modifications copyright (c) 2025 tanchekwei
2+
// Licensed under the MIT License. See the LICENSE file in the project root for details.
3+
using System;
4+
using System.IO;
5+
using System.Runtime.CompilerServices;
6+
using Microsoft.CommandPalette.Extensions.Toolkit;
7+
8+
namespace WorkspaceLauncherForVSCode.Classes
9+
{
10+
internal static class ErrorLogger
11+
{
12+
private static readonly string LogDir = Utilities.BaseSettingsPath(Constant.AppName);
13+
private static readonly string LogFilePath = Path.Combine(LogDir, "error.log");
14+
private static readonly object _lock = new object();
15+
16+
private const long MaxLogSizeBytes = 1 * 1024 * 1024; // 1 MB
17+
private const int MaxArchivedLogs = 5;
18+
19+
public static void LogError(Exception ex, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "")
20+
{
21+
try
22+
{
23+
lock (_lock)
24+
{
25+
Directory.CreateDirectory(LogDir);
26+
27+
if (File.Exists(LogFilePath) && new FileInfo(LogFilePath).Length >= MaxLogSizeBytes)
28+
{
29+
RollLogFiles();
30+
}
31+
32+
var className = Path.GetFileNameWithoutExtension(sourceFilePath);
33+
var logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] [{className}.{memberName}] {ex}{Environment.NewLine}";
34+
File.AppendAllText(LogFilePath, logMessage);
35+
}
36+
}
37+
catch
38+
{
39+
// Suppress exceptions during logging to avoid crashing the app.
40+
}
41+
}
42+
43+
private static void RollLogFiles()
44+
{
45+
try
46+
{
47+
var oldest = Path.Combine(LogDir, $"error_{MaxArchivedLogs}.log");
48+
if (File.Exists(oldest))
49+
{
50+
File.Delete(oldest);
51+
}
52+
53+
for (int i = MaxArchivedLogs - 1; i >= 1; i--)
54+
{
55+
var src = Path.Combine(LogDir, $"error_{i}.log");
56+
var dest = Path.Combine(LogDir, $"error_{i + 1}.log");
57+
58+
if (File.Exists(src))
59+
{
60+
File.Move(src, dest, overwrite: true);
61+
}
62+
}
63+
64+
if (File.Exists(LogFilePath))
65+
{
66+
File.Move(LogFilePath, Path.Combine(LogDir, "error_1.log"), overwrite: true);
67+
}
68+
}
69+
catch
70+
{
71+
// Don't let log rotation failure affect the app
72+
}
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)