lizard 1.17.30__py2.py3-none-any.whl → 1.18.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,6 @@ Language parser for JavaScript
5
5
  import re
6
6
  from .code_reader import CodeReader, CodeStateMachine
7
7
  from .clike import CCppCommentsMixin
8
- from .js_style_language_states import JavaScriptStyleLanguageStates
9
8
  from .js_style_regex_expression import js_style_regex_expression
10
9
 
11
10
 
@@ -64,17 +63,26 @@ class TypeScriptReader(CodeReader, CCppCommentsMixin):
64
63
  def generate_tokens(source_code, addition='', token_class=None):
65
64
  def split_template_literal(token, quote):
66
65
  content = token[1:-1]
66
+
67
+ # Always yield opening quote
68
+ yield quote
69
+
70
+ # If no expressions, yield content as-is with quotes and closing quote
71
+ if '${' not in content:
72
+ if content:
73
+ yield quote + content + quote
74
+ yield quote
75
+ return
76
+
77
+ # Handle expressions
67
78
  i = 0
68
- # Special case for double-quoted strings starting with ${
69
- if quote == '"' and content.startswith('${'):
70
- yield '""'
71
79
  while i < len(content):
72
80
  idx = content.find('${', i)
73
81
  if idx == -1:
74
82
  if i < len(content):
75
83
  yield quote + content[i:] + quote
76
84
  break
77
- if idx > i and not (quote == '"' and idx == 0 and content.startswith('${')):
85
+ if idx > i:
78
86
  yield quote + content[i:idx] + quote
79
87
  yield '${'
80
88
  i = idx + 2
@@ -91,25 +99,35 @@ class TypeScriptReader(CodeReader, CCppCommentsMixin):
91
99
  yield '}'
92
100
  content = content[i:]
93
101
  i = 0
102
+
103
+ # Always yield closing quote
104
+ yield quote
105
+
94
106
  # Restore original addition pattern for template literals
95
107
  addition = addition + r"|(?:\$\w+)" + r"|(?:\w+\?)" + r"|`.*?`"
96
108
  for token in CodeReader.generate_tokens(source_code, addition, token_class):
97
109
  if (
98
110
  isinstance(token, str)
99
- and (token.startswith('`') or token.startswith('"'))
100
- and token[0] == token[-1]
101
- and '${' in token
111
+ and token.startswith('`')
112
+ and token.endswith('`')
113
+ and len(token) > 1
102
114
  ):
103
- quote = token[0]
104
- for t in split_template_literal(token, quote):
115
+ for t in split_template_literal(token, '`'):
105
116
  yield t
106
117
  continue
107
118
  yield token
108
119
 
109
120
 
110
- class TypeScriptStates(JavaScriptStyleLanguageStates):
121
+ class TypeScriptStates(CodeStateMachine):
111
122
  def __init__(self, context):
112
123
  super().__init__(context)
124
+ self.last_tokens = ''
125
+ self.function_name = ''
126
+ self.started_function = None
127
+ self.as_object = False
128
+ self._getter_setter_prefix = None
129
+ self.arrow_function_pending = False
130
+ self._ts_declare = False # Track if 'declare' was seen
113
131
 
114
132
  def statemachine_before_return(self):
115
133
  # Ensure the main function is closed at the end
@@ -117,17 +135,199 @@ class TypeScriptStates(JavaScriptStyleLanguageStates):
117
135
  self._pop_function_from_stack()
118
136
 
119
137
  def _state_global(self, token):
138
+ if token == 'declare':
139
+ self._ts_declare = True
140
+ return
141
+ if token == 'function' and getattr(self, '_ts_declare', False):
142
+ # Skip declared function
143
+ self._ts_declare = False
144
+ # Skip tokens until semicolon or newline
145
+
146
+ def skip_declared_function(t):
147
+ if t == ';' or self.context.newline:
148
+ self.next(self._state_global)
149
+ return True
150
+ return False
151
+ self.next(skip_declared_function)
152
+ return
153
+ self._ts_declare = False
154
+
155
+ if self.as_object:
156
+ # Support for getter/setter: look for 'get' or 'set' before method name
157
+ if token in ('get', 'set'):
158
+ self._getter_setter_prefix = token
159
+ return
160
+ if hasattr(self, '_getter_setter_prefix') and self._getter_setter_prefix:
161
+ # Next token is the property name
162
+ self.last_tokens = f"{self._getter_setter_prefix} {token}"
163
+ self._getter_setter_prefix = None
164
+ return
165
+ if token == '[':
166
+ self._collect_computed_name()
167
+ return
168
+ if token == ':':
169
+ self.function_name = self.last_tokens
170
+ return
171
+ elif token == '(':
172
+ if not self.started_function:
173
+ self.arrow_function_pending = True
174
+ self._function(self.last_tokens)
175
+ self.next(self._function, token)
176
+ return
177
+
178
+ if token in '.':
179
+ self._state = self._field
180
+ self.last_tokens += token
181
+ return
182
+ if token == 'function':
183
+ self._state = self._function
184
+ elif token in ('if', 'switch', 'for', 'while', 'catch'):
185
+ self.next(self._expecting_condition_and_statement_block)
186
+ elif token in ('else', 'do', 'try', 'final'):
187
+ self.next(self._expecting_statement_or_block)
188
+ elif token in ('=>',):
189
+ # Only handle arrow function body, do not push function here
190
+ self._state = self._arrow_function
191
+ elif token == '=':
192
+ self.function_name = self.last_tokens
193
+ elif token == "(":
194
+ self.sub_state(
195
+ self.__class__(self.context))
196
+ elif token in '{':
197
+ if self.started_function:
198
+ self.sub_state(
199
+ self.__class__(self.context),
200
+ self._pop_function_from_stack)
201
+ else:
202
+ self.read_object()
203
+ elif token in ('}', ')'):
204
+ self.statemachine_return()
205
+ elif self.context.newline or token == ';':
206
+ self.function_name = ''
207
+ self._pop_function_from_stack()
208
+
209
+ if token == '`':
210
+ self.next(self._state_template_literal)
120
211
  if not self.as_object:
121
212
  if token == ':':
122
213
  self._consume_type_annotation()
123
214
  return
124
- super()._state_global(token)
215
+ self.last_tokens = token
216
+
217
+ def read_object(self):
218
+ def callback():
219
+ self.next(self._state_global)
220
+
221
+ object_reader = self.__class__(self.context)
222
+ object_reader.as_object = True
223
+ self.sub_state(object_reader, callback)
224
+
225
+ def _expecting_condition_and_statement_block(self, token):
226
+ def callback():
227
+ self.next(self._expecting_statement_or_block)
228
+
229
+ if token == "await":
230
+ return
231
+
232
+ if token != '(':
233
+ self.next(self._state_global, token)
234
+ return
235
+
236
+ self.sub_state(
237
+ self.__class__(self.context), callback)
238
+
239
+ def _expecting_statement_or_block(self, token):
240
+ def callback():
241
+ self.next(self._state_global)
242
+ if token == "{":
243
+ self.sub_state(
244
+ self.__class__(self.context), callback)
245
+ else:
246
+ self.next(self._state_global, token)
247
+
248
+ def _push_function_to_stack(self):
249
+ self.started_function = True
250
+ self.context.push_new_function(self.function_name or '(anonymous)')
251
+
252
+ def _pop_function_from_stack(self):
253
+ if self.started_function:
254
+ self.context.end_of_function()
255
+ self.started_function = None
256
+
257
+ def _arrow_function(self, token):
258
+ self._push_function_to_stack()
259
+ # Handle arrow function body
260
+ if token == '{':
261
+ # Block body
262
+ self.next(self._state_global, token)
263
+ else:
264
+ # Expression body
265
+ self.next(self._state_global, token)
266
+
267
+ def _function(self, token):
268
+ if token == '*':
269
+ return
270
+ if token != '(':
271
+ self.function_name = token
272
+ else:
273
+ if not self.started_function:
274
+ self._push_function_to_stack()
275
+ self.arrow_function_pending = False
276
+ self._state = self._dec
277
+ if token == '(':
278
+ self._dec(token)
279
+
280
+ def _field(self, token):
281
+ self.last_tokens += token
282
+ self._state = self._state_global
283
+
284
+ def _dec(self, token):
285
+ if token == ')':
286
+ self._state = self._expecting_func_opening_bracket
287
+ elif token != '(':
288
+ self.context.parameter(token)
289
+ return
290
+ self.context.add_to_long_function_name(" " + token)
125
291
 
126
292
  def _expecting_func_opening_bracket(self, token):
293
+ # Do not reset started_function for arrow functions (=>)
127
294
  if token == ':':
128
295
  self._consume_type_annotation()
129
- else:
130
- super()._expecting_func_opening_bracket(token)
296
+ elif token != '{' and token != '=>':
297
+ self.started_function = None
298
+ self.next(self._state_global, token)
299
+
300
+ def _state_template_literal(self, token):
301
+ if token == '`':
302
+ self.next(self._state_global)
303
+
304
+ def _collect_computed_name(self):
305
+ # Collect tokens between [ and ]
306
+ tokens = []
307
+
308
+ def collect(token):
309
+ if token == ']':
310
+ # Try to join tokens and camelCase if possible
311
+ name = ''.join(tokens)
312
+ # Remove quotes and pluses for simple cases
313
+ name = name.replace("'", '').replace('"', '').replace('+', '').replace(' ', '')
314
+ # Lowercase first char, uppercase next word's first char
315
+ name = self._to_camel_case(name)
316
+ self.last_tokens = name
317
+ self.next(self._state_global)
318
+ return True
319
+ tokens.append(token)
320
+ return False
321
+ self.next(collect)
322
+
323
+ def _to_camel_case(self, s):
324
+ # Simple camelCase conversion for test case
325
+ if not s:
326
+ return s
327
+ parts = s.split()
328
+ if not parts:
329
+ return s
330
+ return parts[0][0].lower() + parts[0][1:] + ''.join(p.capitalize() for p in parts[1:])
131
331
 
132
332
  def _consume_type_annotation(self):
133
333
  typeStates = TypeScriptTypeAnnotationStates(self.context)
@@ -169,7 +369,7 @@ class TypeScriptTypeAnnotationStates(CodeStateMachine):
169
369
  @CodeStateMachine.read_inside_brackets_then("<>")
170
370
  def _state_generic_type(self, token):
171
371
  self.statemachine_return()
172
-
372
+
173
373
  @CodeStateMachine.read_inside_brackets_then("()")
174
374
  def _function_type_annotation(self, _):
175
375
  self.statemachine_return()
@@ -1,184 +0,0 @@
1
- '''
2
- "JavaScript style language" includes JavaScript and PHP
3
- '''
4
-
5
- from .code_reader import CodeStateMachine
6
-
7
-
8
- class JavaScriptStyleLanguageStates(CodeStateMachine): # pylint: disable=R0903
9
- def __init__(self, context):
10
- super(JavaScriptStyleLanguageStates, self).__init__(context)
11
- self.last_tokens = ''
12
- self.function_name = ''
13
- self.started_function = None
14
- self.as_object = False
15
- self._getter_setter_prefix = None
16
- self.arrow_function_pending = False
17
-
18
- def _state_global(self, token):
19
- if self.as_object:
20
- # Support for getter/setter: look for 'get' or 'set' before method name
21
- if token in ('get', 'set'):
22
- self._getter_setter_prefix = token
23
- return
24
- if hasattr(self, '_getter_setter_prefix') and self._getter_setter_prefix:
25
- # Next token is the property name
26
- self.last_tokens = f"{self._getter_setter_prefix} {token}"
27
- self._getter_setter_prefix = None
28
- return
29
- if token == '[':
30
- self._collect_computed_name()
31
- return
32
- if token == ':':
33
- self.function_name = self.last_tokens
34
- return
35
- elif token == '(':
36
- if not self.started_function:
37
- self.arrow_function_pending = True
38
- self._function(self.last_tokens)
39
- self.next(self._function, token)
40
- return
41
-
42
- if token in '.':
43
- self._state = self._field
44
- self.last_tokens += token
45
- return
46
- if token == 'function':
47
- self._state = self._function
48
- elif token in ('if', 'switch', 'for', 'while', 'catch'):
49
- self.next(self._expecting_condition_and_statement_block)
50
- elif token in ('else', 'do', 'try', 'final'):
51
- self.next(self._expecting_statement_or_block)
52
- elif token in ('=>',):
53
- # Only handle arrow function body, do not push function here
54
- self._state = self._arrow_function
55
- elif token == '=':
56
- self.function_name = self.last_tokens
57
- elif token == "(":
58
- self.sub_state(
59
- self.__class__(self.context))
60
- elif token in '{':
61
- if self.started_function:
62
- self.sub_state(
63
- self.__class__(self.context),
64
- self._pop_function_from_stack)
65
- else:
66
- self.read_object()
67
- elif token in ('}', ')'):
68
- self.statemachine_return()
69
- elif self.context.newline or token == ';':
70
- self.function_name = ''
71
- self._pop_function_from_stack()
72
-
73
- self.last_tokens = token
74
-
75
- def read_object(self):
76
- def callback():
77
- self.next(self._state_global)
78
-
79
- object_reader = self.__class__(self.context)
80
- object_reader.as_object = True
81
- self.sub_state(object_reader, callback)
82
-
83
- def statemachine_before_return(self):
84
- self._pop_function_from_stack()
85
-
86
- def _expecting_condition_and_statement_block(self, token):
87
- def callback():
88
- self.next(self._expecting_statement_or_block)
89
-
90
- if token == "await":
91
- return
92
-
93
- if token != '(':
94
- self.next(self._state_global, token)
95
- return
96
-
97
- self.sub_state(
98
- self.__class__(self.context), callback)
99
-
100
- def _expecting_statement_or_block(self, token):
101
- def callback():
102
- self.next(self._state_global)
103
- if token == "{":
104
- self.sub_state(
105
- self.__class__(self.context), callback)
106
- else:
107
- self.next(self._state_global, token)
108
-
109
- def _push_function_to_stack(self):
110
- self.started_function = True
111
- self.context.push_new_function(self.function_name or '(anonymous)')
112
-
113
- def _pop_function_from_stack(self):
114
- if self.started_function:
115
- self.context.end_of_function()
116
- self.started_function = None
117
-
118
- def _arrow_function(self, token):
119
- self._push_function_to_stack()
120
- # Handle arrow function body
121
- if token == '{':
122
- # Block body
123
- self.next(self._state_global, token)
124
- else:
125
- # Expression body
126
- self.next(self._state_global, token)
127
-
128
- def _function(self, token):
129
- if token == '*':
130
- return
131
- if token != '(':
132
- self.function_name = token
133
- else:
134
- if not self.started_function:
135
- self._push_function_to_stack()
136
- self.arrow_function_pending = False
137
- self._state = self._dec
138
- if token == '(':
139
- self._dec(token)
140
-
141
- def _field(self, token):
142
- self.last_tokens += token
143
- self._state = self._state_global
144
-
145
- def _dec(self, token):
146
- if token == ')':
147
- self._state = self._expecting_func_opening_bracket
148
- elif token != '(':
149
- self.context.parameter(token)
150
- return
151
- self.context.add_to_long_function_name(" " + token)
152
-
153
- def _expecting_func_opening_bracket(self, token):
154
- # Do not reset started_function for arrow functions (=>)
155
- if token != '{' and token != '=>':
156
- self.started_function = None
157
- self.next(self._state_global, token)
158
-
159
- def _collect_computed_name(self):
160
- # Collect tokens between [ and ]
161
- tokens = []
162
- def collect(token):
163
- if token == ']':
164
- # Try to join tokens and camelCase if possible
165
- name = ''.join(tokens)
166
- # Remove quotes and pluses for simple cases
167
- name = name.replace("'", '').replace('"', '').replace('+', '').replace(' ', '')
168
- # Lowercase first char, uppercase next word's first char
169
- name = self._to_camel_case(name)
170
- self.last_tokens = name
171
- self.next(self._state_global)
172
- return True
173
- tokens.append(token)
174
- return False
175
- self.next(collect)
176
-
177
- def _to_camel_case(self, s):
178
- # Simple camelCase conversion for test case
179
- if not s:
180
- return s
181
- parts = s.split()
182
- if not parts:
183
- return s
184
- return parts[0][0].lower() + parts[0][1:] + ''.join(p.capitalize() for p in parts[1:])