|
12 | 12 | var tree = CSharpSyntaxTree.ParseText(code); |
13 | 13 | var nodes = tree.GetCompilationUnitRoot() |
14 | 14 | .Blacklist<MethodDeclarationSyntax>( |
15 | | - // NSObject |
16 | | - "IsEqual", |
17 | | - "CopyWithZone", |
18 | | - // PrivateSentrySDKOnly |
19 | | - "StoreEnvelope", |
20 | | - "CaptureEnvelope", |
21 | | - "EnvelopeWithData", |
22 | | - // SentryOptions |
23 | | - "CaptureUserFeedback" |
| 15 | + // error CS0114: 'SentryXxx.IsEqual(NSObject?)' hides inherited member 'NSObject.IsEqual(NSObject?)'. |
| 16 | + "Sentry*.IsEqual", |
| 17 | + // error CS0246: The type or namespace name '_NSZone' could not be found |
| 18 | + "Sentry*.CopyWithZone", |
| 19 | + // SentryEnvelope* is blacklisted |
| 20 | + "PrivateSentrySDKOnly.CaptureEnvelope", |
| 21 | + "PrivateSentrySDKOnly.EnvelopeWithData", |
| 22 | + "PrivateSentrySDKOnly.StoreEnvelope", |
| 23 | + // deprecated |
| 24 | + "Sentry*.CaptureUserFeedback" |
24 | 25 | ) |
25 | 26 | .Blacklist<DelegateDeclarationSyntax>( |
| 27 | + // deprecated |
26 | 28 | "SentryUserFeedbackConfigurationBlock" |
27 | 29 | ) |
28 | 30 | .Blacklist<PropertyDeclarationSyntax>( |
29 | | - "ConfigureUserFeedback", |
30 | | - "Description", |
31 | | - "EnableMetricKitRawPayload", |
32 | | - "AppStartMeasurement", |
33 | | - "AppStartMeasurementTimeoutInterval", |
34 | | - "OnAppStartMeasurementAvailable", |
35 | | - "SentryExperimentalOptions", |
36 | | - "SpanDescription" |
| 31 | + // error CS0114: 'SentryXxx.Description' hides inherited member 'NSObject.Description'. |
| 32 | + "Sentry*.Description", |
| 33 | + // SentryAppStartMeasurement is not whitelisted |
| 34 | + "PrivateSentrySDKOnly.*AppStartMeasurement*", |
| 35 | + // deprecated |
| 36 | + "SentryOptions.ConfigureUserFeedback" |
37 | 37 | ) |
38 | 38 | .Whitelist<InterfaceDeclarationSyntax>( |
39 | 39 | "Constants", |
@@ -108,25 +108,70 @@ private static string GetIdentifier(SyntaxNode node) |
108 | 108 | }; |
109 | 109 | } |
110 | 110 |
|
| 111 | + private static string GetQualifiedName(SyntaxNode node) |
| 112 | + { |
| 113 | + var identifier = GetIdentifier(node); |
| 114 | + var parent = node.Parent; |
| 115 | + while (parent != null) |
| 116 | + { |
| 117 | + if (parent is TypeDeclarationSyntax typeDecl) |
| 118 | + { |
| 119 | + return $"{typeDecl.Identifier.Text}.{identifier}"; |
| 120 | + } |
| 121 | + parent = parent.Parent; |
| 122 | + } |
| 123 | + return identifier; |
| 124 | + } |
| 125 | + |
| 126 | + private static bool MatchesPattern(string name, string pattern) |
| 127 | + { |
| 128 | + if (pattern == name) |
| 129 | + { |
| 130 | + return true; |
| 131 | + } |
| 132 | + |
| 133 | + if (!pattern.Contains('*') && !pattern.Contains('?')) |
| 134 | + { |
| 135 | + return false; |
| 136 | + } |
| 137 | + |
| 138 | + var regexPattern = "^" + Regex.Escape(pattern) |
| 139 | + .Replace("\\*", ".*") |
| 140 | + .Replace("\\?", ".") + "$"; |
| 141 | + return Regex.IsMatch(name, regexPattern); |
| 142 | + } |
| 143 | + |
| 144 | + private static bool MatchesName(SyntaxNode node, string[] patterns) |
| 145 | + { |
| 146 | + var identifier = GetIdentifier(node); |
| 147 | + var qualifiedName = GetQualifiedName(node); |
| 148 | + foreach (var pattern in patterns) |
| 149 | + { |
| 150 | + if (MatchesPattern(identifier, pattern) || MatchesPattern(qualifiedName, pattern)) |
| 151 | + { |
| 152 | + return true; |
| 153 | + } |
| 154 | + } |
| 155 | + return false; |
| 156 | + } |
| 157 | + |
111 | 158 | public static CompilationUnitSyntax Blacklist<T>( |
112 | 159 | this CompilationUnitSyntax root, |
113 | 160 | params string[] names) where T : SyntaxNode |
114 | 161 | { |
115 | | - var nameSet = new HashSet<string>(names); |
116 | 162 | var nodesToRemove = root.DescendantNodes() |
117 | 163 | .OfType<T>() |
118 | | - .Where(node => nameSet.Contains(GetIdentifier(node))); |
| 164 | + .Where(node => MatchesName(node, names)); |
119 | 165 | return root.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia)!; |
120 | 166 | } |
121 | 167 |
|
122 | 168 | public static CompilationUnitSyntax Whitelist<T>( |
123 | 169 | this CompilationUnitSyntax root, |
124 | 170 | params string[] names) where T : SyntaxNode |
125 | 171 | { |
126 | | - var nameSet = new HashSet<string>(names); |
127 | 172 | var nodesToRemove = root.DescendantNodes() |
128 | 173 | .OfType<T>() |
129 | | - .Where(node => !nameSet.Contains(GetIdentifier(node))); |
| 174 | + .Where(node => !MatchesName(node, names)); |
130 | 175 | return root.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia)!; |
131 | 176 | } |
132 | 177 | } |
0 commit comments