-
Notifications
You must be signed in to change notification settings - Fork 2
/
retools.py
83 lines (74 loc) · 2.52 KB
/
retools.py
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Copyright 2018-19 Quantcast Corporation. All rights reserved.
#
# This file is part of Quantcast Apex Linter for Salesforce
#
# Licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.
#
import re
from typing import Optional, Pattern, Union
PatternOrStr = Union[str, Pattern]
def escape(s: PatternOrStr, flags: Optional[int] = None) -> Pattern:
"""Return Pattern object for `s`, escaping it if necessary.
If `flags` is not None, clobber any flags on `s`.
"""
if isinstance(s, Pattern):
if flags is not None:
s = re.compile(s.pattern, flags=flags)
return s
return re.compile(re.escape(s), flags=(flags or 0))
def comment(s: PatternOrStr) -> Pattern:
"""Return Pattern object that matches `s` inside a comment."""
pattern = escape(s)
return not_string(
fr"""
(?x: # Match s inside a comment
/\* # C-style /* comment */
(\*(?!\/)|[^*])*? # Ignore closing */
(?-x:(?P<c>{pattern.pattern}))
.*?
\*/
|
// # C++-style // comment
.*?
(?-x:(?P<cpp>{pattern.pattern}))
)
""".strip(),
flags=pattern.flags,
)
def not_string(s: PatternOrStr, flags: int = 0) -> Pattern:
"""Return Pattern object that matches `s` outside quoted strings."""
if isinstance(s, Pattern):
flags = s.flags
s = str(s.pattern)
return re.compile(
fr"""
(?x: # Ensure we are outside a single-quoted string
^
(?: # Match pairs of single-quotes
[^']*
'
(?:
\\\\ # Quoted backslash: \\
|
\\' # Quoted apostrophe: \'
|
[^'\\] # Not the ending quote or a dangling backslash
)*
'
)*
[^']*
)
""".strip()
+ s,
flags=flags,
)