sflkit 0.5.3__tar.gz → 0.5.5__tar.gz
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.
- {sflkit-0.5.3/src/sflkit.egg-info → sflkit-0.5.5}/PKG-INFO +1 -1
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/__init__.py +1 -1
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/factory.py +63 -22
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/spectra.py +7 -1
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/instrumentation/file_instrumentation.py +6 -1
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/meta.py +50 -21
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/factory.py +188 -6
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/visitor.py +2 -1
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/model/parallel.py +10 -10
- sflkit-0.5.5/src/sflkit/model/scope.py +82 -0
- {sflkit-0.5.3 → sflkit-0.5.5/src/sflkit.egg-info}/PKG-INFO +1 -1
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/SOURCES.txt +1 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_analysis_objects.py +4 -1
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_config.py +4 -1
- sflkit-0.5.5/tests/test_expression.py +181 -0
- sflkit-0.5.5/tests/test_scope.py +43 -0
- sflkit-0.5.3/src/sflkit/model/scope.py +0 -39
- sflkit-0.5.3/tests/test_scope.py +0 -20
- {sflkit-0.5.3 → sflkit-0.5.5}/LICENSE +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/README.md +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/pyproject.toml +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/setup.cfg +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/analysis_type.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/analyzer.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/mapping.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/predicate.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/similarity.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/analysis/suggestion.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/cli.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/color.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/config.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/evaluation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/events/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/events/event_file.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/events/mapping.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/features/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/features/handler.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/features/value.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/features/vector.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/instrumentation/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/extract.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/finder.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/extract.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/factory.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/finder.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/java/visitor.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/language.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/extract.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/finder.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/language/python/visitor.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/logger.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/model/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/model/model.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/runners/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/runners/run.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/weights/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/weights/analyzer.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit/weights/models.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/dependency_links.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/entry_points.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/requires.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/src/sflkit.egg-info/top_level.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_analyzer.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_cli.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_color.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_coverage.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_dependency_weights.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_evaluation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_events.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_execution.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_features.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_instrumentation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_language.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_parallelization.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_predicates.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_runner.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_runner_parallel.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_runner_pytest_versions.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_spectra.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_suggestions.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.5}/tests/test_visitors.py +0 -0
|
@@ -85,7 +85,7 @@ class LineFactory(AnalysisFactory):
|
|
|
85
85
|
if key not in self.objects:
|
|
86
86
|
self.objects[key] = Line(event)
|
|
87
87
|
return [self.objects[key]]
|
|
88
|
-
return
|
|
88
|
+
return []
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
class BranchFactory(AnalysisFactory):
|
|
@@ -117,7 +117,7 @@ class BranchFactory(AnalysisFactory):
|
|
|
117
117
|
return [self.objects[key], self.objects[else_key]]
|
|
118
118
|
return [self.objects[key]]
|
|
119
119
|
|
|
120
|
-
return
|
|
120
|
+
return []
|
|
121
121
|
|
|
122
122
|
|
|
123
123
|
class FunctionFactory(AnalysisFactory):
|
|
@@ -130,7 +130,7 @@ class FunctionFactory(AnalysisFactory):
|
|
|
130
130
|
if key not in self.objects:
|
|
131
131
|
self.objects[key] = Function(event)
|
|
132
132
|
return [self.objects[key]]
|
|
133
|
-
return
|
|
133
|
+
return []
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
class LoopFactory(AnalysisFactory):
|
|
@@ -170,27 +170,70 @@ class LoopFactory(AnalysisFactory):
|
|
|
170
170
|
elif event.event_type == EventType.LOOP_END:
|
|
171
171
|
return self.objects[key][:]
|
|
172
172
|
return list()
|
|
173
|
-
return
|
|
173
|
+
return []
|
|
174
174
|
|
|
175
175
|
|
|
176
176
|
class DefUseFactory(AnalysisFactory):
|
|
177
177
|
def __init__(self):
|
|
178
178
|
super().__init__()
|
|
179
179
|
self.id_to_def: dict[EventFile, dict[tuple[str, int], DefEvent]] = dict()
|
|
180
|
+
self.def_stack: dict[EventFile, dict[int, dict[tuple[str, int], DefEvent]]] = (
|
|
181
|
+
dict()
|
|
182
|
+
)
|
|
180
183
|
|
|
181
184
|
def reset(self, event_file: EventFile):
|
|
182
|
-
|
|
183
|
-
self.id_to_def[event_file]
|
|
185
|
+
if event_file in self.id_to_def:
|
|
186
|
+
del self.id_to_def[event_file]
|
|
187
|
+
if event_file in self.def_stack:
|
|
188
|
+
del self.def_stack[event_file]
|
|
189
|
+
|
|
190
|
+
def _find_def_event(
|
|
191
|
+
self,
|
|
192
|
+
event_file: EventFile,
|
|
193
|
+
scope_id: int,
|
|
194
|
+
var_name: str,
|
|
195
|
+
var_id: int,
|
|
196
|
+
) -> DefEvent:
|
|
197
|
+
# Strategy 1: Check in scope
|
|
198
|
+
def_event = None
|
|
199
|
+
if event_file in self.def_stack and scope_id in self.def_stack[event_file]:
|
|
200
|
+
def_event = self.def_stack[event_file][scope_id].get(
|
|
201
|
+
(var_name, var_id), None
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Strategy 2: Look up in the global DEF stack (other threads)
|
|
205
|
+
if def_event is None:
|
|
206
|
+
if event_file in self.id_to_def:
|
|
207
|
+
def_event = self.id_to_def[event_file].get((var_name, var_id), None)
|
|
208
|
+
|
|
209
|
+
return def_event
|
|
184
210
|
|
|
185
211
|
def get_analysis(
|
|
186
212
|
self, event, event_file: EventFile, scope: Scope = None
|
|
187
213
|
) -> List[AnalysisObject]:
|
|
214
|
+
thread_id = event.thread_id
|
|
215
|
+
scope_id = scope.id if scope else 0
|
|
216
|
+
|
|
188
217
|
if event.event_type == EventType.DEF:
|
|
189
|
-
|
|
190
|
-
|
|
218
|
+
key = (event.var, event.var_id)
|
|
219
|
+
|
|
220
|
+
# Initialize structures if needed
|
|
221
|
+
if event_file not in self.id_to_def:
|
|
222
|
+
self.id_to_def[event_file] = dict()
|
|
223
|
+
if event_file not in self.def_stack:
|
|
224
|
+
self.def_stack[event_file] = dict()
|
|
225
|
+
if scope_id not in self.def_stack[event_file]:
|
|
226
|
+
self.def_stack[event_file][scope_id] = dict()
|
|
227
|
+
|
|
228
|
+
# Store the DEF event
|
|
229
|
+
self.id_to_def[event_file][key] = event
|
|
230
|
+
self.def_stack[event_file][scope_id][key] = event
|
|
231
|
+
|
|
191
232
|
elif event.event_type == EventType.USE:
|
|
192
|
-
|
|
193
|
-
|
|
233
|
+
def_event = self._find_def_event(
|
|
234
|
+
event_file, scope_id, event.var, event.var_id
|
|
235
|
+
)
|
|
236
|
+
|
|
194
237
|
if def_event:
|
|
195
238
|
key = (
|
|
196
239
|
DefUse.analysis_type(),
|
|
@@ -204,7 +247,7 @@ class DefUseFactory(AnalysisFactory):
|
|
|
204
247
|
if key not in self.objects:
|
|
205
248
|
self.objects[key] = DefUse(def_event, event)
|
|
206
249
|
return [self.objects[key]]
|
|
207
|
-
return
|
|
250
|
+
return []
|
|
208
251
|
|
|
209
252
|
|
|
210
253
|
class ConditionFactory(AnalysisFactory):
|
|
@@ -305,7 +348,7 @@ class ScalarPairFactory(ComparisonFactory):
|
|
|
305
348
|
)
|
|
306
349
|
objects.append(self.objects[key])
|
|
307
350
|
return objects
|
|
308
|
-
return
|
|
351
|
+
return []
|
|
309
352
|
|
|
310
353
|
|
|
311
354
|
class VariableFactory(ComparisonFactory):
|
|
@@ -332,7 +375,7 @@ class VariableFactory(ComparisonFactory):
|
|
|
332
375
|
self.objects[key] = VariablePredicate(event, comp)
|
|
333
376
|
objects.append(self.objects[key])
|
|
334
377
|
return objects
|
|
335
|
-
return
|
|
378
|
+
return []
|
|
336
379
|
|
|
337
380
|
|
|
338
381
|
class ReturnFactory(ComparisonFactory):
|
|
@@ -402,7 +445,7 @@ class ReturnFactory(ComparisonFactory):
|
|
|
402
445
|
)
|
|
403
446
|
objects.append(self.objects[key])
|
|
404
447
|
return objects
|
|
405
|
-
return
|
|
448
|
+
return []
|
|
406
449
|
|
|
407
450
|
|
|
408
451
|
class ConstantCompFactory(AnalysisFactory):
|
|
@@ -429,7 +472,7 @@ class ConstantCompFactory(AnalysisFactory):
|
|
|
429
472
|
self.objects[key] = self.class_(event)
|
|
430
473
|
objects.append(self.objects[key])
|
|
431
474
|
return objects
|
|
432
|
-
return
|
|
475
|
+
return []
|
|
433
476
|
|
|
434
477
|
|
|
435
478
|
class NoneFactory(ConstantCompFactory):
|
|
@@ -467,7 +510,7 @@ class PredicateFunctionFactory(AnalysisFactory):
|
|
|
467
510
|
# noinspection PyArgumentList
|
|
468
511
|
self.objects[key] = self.class_(event)
|
|
469
512
|
return [self.objects[key]]
|
|
470
|
-
return
|
|
513
|
+
return []
|
|
471
514
|
|
|
472
515
|
|
|
473
516
|
class IsAsciiFactory(PredicateFunctionFactory):
|
|
@@ -518,7 +561,7 @@ class LengthFactory(AnalysisFactory):
|
|
|
518
561
|
Length(event, Length.evaluate_length_more)
|
|
519
562
|
)
|
|
520
563
|
return self.objects[key][:]
|
|
521
|
-
return
|
|
564
|
+
return []
|
|
522
565
|
|
|
523
566
|
|
|
524
567
|
class FunctionErrorFactory(AnalysisFactory):
|
|
@@ -530,11 +573,9 @@ class FunctionErrorFactory(AnalysisFactory):
|
|
|
530
573
|
self, event, event_file: EventFile, scope: Scope = None
|
|
531
574
|
) -> List[AnalysisObject]:
|
|
532
575
|
if event.event_type == EventType.FUNCTION_ENTER:
|
|
533
|
-
|
|
534
|
-
self.function_mapping[event.function_id] = event.line
|
|
576
|
+
self.function_mapping[event.function_id] = event.line
|
|
535
577
|
if event.event_type in (EventType.FUNCTION_ERROR, EventType.FUNCTION_EXIT):
|
|
536
|
-
|
|
537
|
-
line = self.function_mapping.get(event.function_id, event.line)
|
|
578
|
+
line = self.function_mapping.get(event.function_id, event.line)
|
|
538
579
|
key = (
|
|
539
580
|
FunctionErrorPredicate.analysis_type(),
|
|
540
581
|
event.file,
|
|
@@ -547,7 +588,7 @@ class FunctionErrorFactory(AnalysisFactory):
|
|
|
547
588
|
event.file, line, event.function
|
|
548
589
|
)
|
|
549
590
|
return [self.objects[key]]
|
|
550
|
-
return
|
|
591
|
+
return []
|
|
551
592
|
|
|
552
593
|
|
|
553
594
|
analysis_factory_mapping = {
|
|
@@ -722,7 +722,13 @@ class DefUse(Spectrum):
|
|
|
722
722
|
|
|
723
723
|
@staticmethod
|
|
724
724
|
def events():
|
|
725
|
-
return [
|
|
725
|
+
return [
|
|
726
|
+
EventType.DEF,
|
|
727
|
+
EventType.USE,
|
|
728
|
+
EventType.FUNCTION_ENTER,
|
|
729
|
+
EventType.FUNCTION_EXIT,
|
|
730
|
+
EventType.FUNCTION_ERROR,
|
|
731
|
+
]
|
|
726
732
|
|
|
727
733
|
def get_suggestion(
|
|
728
734
|
self, metric: Callable = None, base_dir: str = "", use_weight: bool = False
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from typing import List, Optional
|
|
3
4
|
|
|
@@ -11,7 +12,11 @@ class FileInstrumentation(Instrumentation):
|
|
|
11
12
|
super().__init__(visitor, mapping_path)
|
|
12
13
|
|
|
13
14
|
def instrument(
|
|
14
|
-
self,
|
|
15
|
+
self,
|
|
16
|
+
src: os.PathLike,
|
|
17
|
+
dst: os.PathLike,
|
|
18
|
+
suffixes: List[str] = None,
|
|
19
|
+
file: str = "",
|
|
15
20
|
):
|
|
16
21
|
self.visitor.instrument(src, dst, file)
|
|
17
22
|
self.events = EventMapping(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import random
|
|
2
2
|
from abc import ABC
|
|
3
|
+
from threading import Lock
|
|
3
4
|
from typing import List, Type, Any
|
|
4
5
|
|
|
5
6
|
from sflkitlib.events.event import Event
|
|
@@ -60,10 +61,12 @@ class Injection:
|
|
|
60
61
|
class IDGenerator:
|
|
61
62
|
def __init__(self):
|
|
62
63
|
self.current_id = 0
|
|
64
|
+
self.lock = Lock()
|
|
63
65
|
|
|
64
66
|
def get_next_id(self):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
with self.lock:
|
|
68
|
+
id_ = self.current_id
|
|
69
|
+
self.current_id += 1
|
|
67
70
|
return id_
|
|
68
71
|
|
|
69
72
|
|
|
@@ -85,6 +88,7 @@ class MetaVisitor(ABC):
|
|
|
85
88
|
event_id_generator: IDGenerator,
|
|
86
89
|
function_id_generator: IDGenerator,
|
|
87
90
|
tmp_generator: TmpGenerator,
|
|
91
|
+
order: int = 0,
|
|
88
92
|
**kwargs,
|
|
89
93
|
):
|
|
90
94
|
self.event_id_generator = event_id_generator
|
|
@@ -95,6 +99,27 @@ class MetaVisitor(ABC):
|
|
|
95
99
|
self.condition_extract = language.condition_extract
|
|
96
100
|
self.event_count = 0
|
|
97
101
|
self.file = None
|
|
102
|
+
self.order = order
|
|
103
|
+
|
|
104
|
+
def __lt__(self, other):
|
|
105
|
+
if not isinstance(other, MetaVisitor):
|
|
106
|
+
raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
|
|
107
|
+
return self.order < other.order
|
|
108
|
+
|
|
109
|
+
def __gt__(self, other):
|
|
110
|
+
if not isinstance(other, MetaVisitor):
|
|
111
|
+
raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
|
|
112
|
+
return self.order > other.order
|
|
113
|
+
|
|
114
|
+
def __le__(self, other):
|
|
115
|
+
if not isinstance(other, MetaVisitor):
|
|
116
|
+
raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
|
|
117
|
+
return self.order <= other.order
|
|
118
|
+
|
|
119
|
+
def __ge__(self, other):
|
|
120
|
+
if not isinstance(other, MetaVisitor):
|
|
121
|
+
raise TypeError(f"Cannot compare MetaVisitor with {type(other)}")
|
|
122
|
+
return self.order >= other.order
|
|
98
123
|
|
|
99
124
|
def get_event_call(self, event: Event):
|
|
100
125
|
pass
|
|
@@ -145,26 +170,30 @@ class CombinationVisitor(MetaVisitor):
|
|
|
145
170
|
tmp_generator,
|
|
146
171
|
)
|
|
147
172
|
if test:
|
|
148
|
-
self.visitors =
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
self.visitors = sorted(
|
|
174
|
+
[
|
|
175
|
+
visitor(
|
|
176
|
+
language,
|
|
177
|
+
event_id_generator,
|
|
178
|
+
function_id_generator,
|
|
179
|
+
tmp_generator,
|
|
180
|
+
ignore_inner=ignore_inner,
|
|
181
|
+
)
|
|
182
|
+
for visitor in visitors
|
|
183
|
+
],
|
|
184
|
+
)
|
|
158
185
|
else:
|
|
159
|
-
self.visitors =
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
186
|
+
self.visitors = sorted(
|
|
187
|
+
[
|
|
188
|
+
visitor(
|
|
189
|
+
language,
|
|
190
|
+
event_id_generator,
|
|
191
|
+
function_id_generator,
|
|
192
|
+
tmp_generator,
|
|
193
|
+
)
|
|
194
|
+
for visitor in visitors
|
|
195
|
+
],
|
|
196
|
+
)
|
|
168
197
|
|
|
169
198
|
def visit_start(self, *args) -> Injection:
|
|
170
199
|
injections = Injection()
|
|
@@ -56,10 +56,15 @@ class PythonEventFactory(MetaVisitor, NodeVisitor):
|
|
|
56
56
|
event_id_generator: IDGenerator,
|
|
57
57
|
function_id_generator: IDGenerator,
|
|
58
58
|
tmp_generator: TmpGenerator,
|
|
59
|
+
order: int = 0,
|
|
59
60
|
**kwargs,
|
|
60
61
|
):
|
|
61
62
|
super().__init__(
|
|
62
|
-
language,
|
|
63
|
+
language,
|
|
64
|
+
event_id_generator,
|
|
65
|
+
function_id_generator,
|
|
66
|
+
tmp_generator,
|
|
67
|
+
order=order,
|
|
63
68
|
)
|
|
64
69
|
|
|
65
70
|
def visit_start(self, *args) -> Injection:
|
|
@@ -291,7 +296,21 @@ class DefEventFactory(PythonEventFactory):
|
|
|
291
296
|
def visit_AsyncFunctionDef(self, node: AsyncFunctionDef) -> Injection:
|
|
292
297
|
return self.visit_function(node)
|
|
293
298
|
|
|
294
|
-
def get_event(
|
|
299
|
+
def get_event(
|
|
300
|
+
self,
|
|
301
|
+
node: typing.Union[
|
|
302
|
+
Assign,
|
|
303
|
+
AnnAssign,
|
|
304
|
+
AugAssign,
|
|
305
|
+
FunctionDef,
|
|
306
|
+
AsyncFunctionDef,
|
|
307
|
+
For,
|
|
308
|
+
AsyncFor,
|
|
309
|
+
With,
|
|
310
|
+
AsyncWith,
|
|
311
|
+
],
|
|
312
|
+
var: str,
|
|
313
|
+
):
|
|
295
314
|
return DefEvent(
|
|
296
315
|
self.file, node.lineno, self.event_id_generator.get_next_id(), var
|
|
297
316
|
)
|
|
@@ -369,18 +388,24 @@ class FunctionEventFactory(PythonEventFactory):
|
|
|
369
388
|
event_id_generator: IDGenerator,
|
|
370
389
|
function_id_generator: IDGenerator,
|
|
371
390
|
tmp_generator: TmpGenerator,
|
|
391
|
+
order: int,
|
|
372
392
|
**kwargs,
|
|
373
393
|
):
|
|
374
394
|
super().__init__(
|
|
375
|
-
language,
|
|
395
|
+
language,
|
|
396
|
+
event_id_generator,
|
|
397
|
+
function_id_generator,
|
|
398
|
+
tmp_generator,
|
|
399
|
+
order=order,
|
|
400
|
+
**kwargs,
|
|
376
401
|
)
|
|
377
402
|
self.function_stack = list()
|
|
378
403
|
|
|
379
404
|
def get_function_id(self, node: AST) -> int:
|
|
380
405
|
if node not in FunctionEventFactory.functions:
|
|
381
|
-
FunctionEventFactory.functions[
|
|
382
|
-
|
|
383
|
-
|
|
406
|
+
FunctionEventFactory.functions[node] = (
|
|
407
|
+
self.function_id_generator.get_next_id()
|
|
408
|
+
)
|
|
384
409
|
return FunctionEventFactory.functions[node]
|
|
385
410
|
|
|
386
411
|
@staticmethod
|
|
@@ -403,6 +428,23 @@ class FunctionEventFactory(PythonEventFactory):
|
|
|
403
428
|
|
|
404
429
|
|
|
405
430
|
class FunctionEnterEventFactory(FunctionEventFactory):
|
|
431
|
+
def __init__(
|
|
432
|
+
self,
|
|
433
|
+
language,
|
|
434
|
+
event_id_generator: IDGenerator,
|
|
435
|
+
function_id_generator: IDGenerator,
|
|
436
|
+
tmp_generator: TmpGenerator,
|
|
437
|
+
**kwargs,
|
|
438
|
+
):
|
|
439
|
+
super().__init__(
|
|
440
|
+
language,
|
|
441
|
+
event_id_generator,
|
|
442
|
+
function_id_generator,
|
|
443
|
+
tmp_generator,
|
|
444
|
+
order=-2,
|
|
445
|
+
**kwargs,
|
|
446
|
+
)
|
|
447
|
+
|
|
406
448
|
def get_function(self):
|
|
407
449
|
return "add_function_enter_event"
|
|
408
450
|
|
|
@@ -441,6 +483,23 @@ class FunctionEnterEventFactory(FunctionEventFactory):
|
|
|
441
483
|
|
|
442
484
|
|
|
443
485
|
class FunctionExitEventFactor(FunctionEventFactory):
|
|
486
|
+
def __init__(
|
|
487
|
+
self,
|
|
488
|
+
language,
|
|
489
|
+
event_id_generator: IDGenerator,
|
|
490
|
+
function_id_generator: IDGenerator,
|
|
491
|
+
tmp_generator: TmpGenerator,
|
|
492
|
+
**kwargs,
|
|
493
|
+
):
|
|
494
|
+
super().__init__(
|
|
495
|
+
language,
|
|
496
|
+
event_id_generator,
|
|
497
|
+
function_id_generator,
|
|
498
|
+
tmp_generator,
|
|
499
|
+
order=2,
|
|
500
|
+
**kwargs,
|
|
501
|
+
)
|
|
502
|
+
|
|
444
503
|
def get_function(self):
|
|
445
504
|
return "add_function_exit_event"
|
|
446
505
|
|
|
@@ -521,6 +580,23 @@ class FunctionExitEventFactor(FunctionEventFactory):
|
|
|
521
580
|
|
|
522
581
|
|
|
523
582
|
class FunctionErrorEventFactory(FunctionEventFactory):
|
|
583
|
+
def __init__(
|
|
584
|
+
self,
|
|
585
|
+
language,
|
|
586
|
+
event_id_generator: IDGenerator,
|
|
587
|
+
function_id_generator: IDGenerator,
|
|
588
|
+
tmp_generator: TmpGenerator,
|
|
589
|
+
**kwargs,
|
|
590
|
+
):
|
|
591
|
+
super().__init__(
|
|
592
|
+
language,
|
|
593
|
+
event_id_generator,
|
|
594
|
+
function_id_generator,
|
|
595
|
+
tmp_generator,
|
|
596
|
+
order=2,
|
|
597
|
+
**kwargs,
|
|
598
|
+
)
|
|
599
|
+
|
|
524
600
|
def get_function(self):
|
|
525
601
|
return "add_function_error_event"
|
|
526
602
|
|
|
@@ -550,6 +626,24 @@ class LoopEventFactory(PythonEventFactory):
|
|
|
550
626
|
loops: typing.Dict[AST, int] = dict()
|
|
551
627
|
loop_id: int = 0
|
|
552
628
|
|
|
629
|
+
def __init__(
|
|
630
|
+
self,
|
|
631
|
+
language,
|
|
632
|
+
event_id_generator: IDGenerator,
|
|
633
|
+
function_id_generator: IDGenerator,
|
|
634
|
+
tmp_generator: TmpGenerator,
|
|
635
|
+
order: int,
|
|
636
|
+
**kwargs,
|
|
637
|
+
):
|
|
638
|
+
super().__init__(
|
|
639
|
+
language,
|
|
640
|
+
event_id_generator,
|
|
641
|
+
function_id_generator,
|
|
642
|
+
tmp_generator,
|
|
643
|
+
order=order,
|
|
644
|
+
**kwargs,
|
|
645
|
+
)
|
|
646
|
+
|
|
553
647
|
@staticmethod
|
|
554
648
|
def get_loop_id(node: AST) -> int:
|
|
555
649
|
if node not in LoopEventFactory.loops:
|
|
@@ -571,6 +665,23 @@ class LoopEventFactory(PythonEventFactory):
|
|
|
571
665
|
|
|
572
666
|
|
|
573
667
|
class LoopBeginEventFactory(LoopEventFactory):
|
|
668
|
+
def __init__(
|
|
669
|
+
self,
|
|
670
|
+
language,
|
|
671
|
+
event_id_generator: IDGenerator,
|
|
672
|
+
function_id_generator: IDGenerator,
|
|
673
|
+
tmp_generator: TmpGenerator,
|
|
674
|
+
**kwargs,
|
|
675
|
+
):
|
|
676
|
+
super().__init__(
|
|
677
|
+
language,
|
|
678
|
+
event_id_generator,
|
|
679
|
+
function_id_generator,
|
|
680
|
+
tmp_generator,
|
|
681
|
+
order=-1,
|
|
682
|
+
**kwargs,
|
|
683
|
+
)
|
|
684
|
+
|
|
574
685
|
def get_function(self):
|
|
575
686
|
return "add_loop_begin_event"
|
|
576
687
|
|
|
@@ -587,6 +698,23 @@ class LoopBeginEventFactory(LoopEventFactory):
|
|
|
587
698
|
|
|
588
699
|
|
|
589
700
|
class LoopHitEventFactory(LoopEventFactory):
|
|
701
|
+
def __init__(
|
|
702
|
+
self,
|
|
703
|
+
language,
|
|
704
|
+
event_id_generator: IDGenerator,
|
|
705
|
+
function_id_generator: IDGenerator,
|
|
706
|
+
tmp_generator: TmpGenerator,
|
|
707
|
+
**kwargs,
|
|
708
|
+
):
|
|
709
|
+
super().__init__(
|
|
710
|
+
language,
|
|
711
|
+
event_id_generator,
|
|
712
|
+
function_id_generator,
|
|
713
|
+
tmp_generator,
|
|
714
|
+
order=-1,
|
|
715
|
+
**kwargs,
|
|
716
|
+
)
|
|
717
|
+
|
|
590
718
|
def get_function(self):
|
|
591
719
|
return "add_loop_hit_event"
|
|
592
720
|
|
|
@@ -603,6 +731,23 @@ class LoopHitEventFactory(LoopEventFactory):
|
|
|
603
731
|
|
|
604
732
|
|
|
605
733
|
class LoopEndEventFactory(LoopEventFactory):
|
|
734
|
+
def __init__(
|
|
735
|
+
self,
|
|
736
|
+
language,
|
|
737
|
+
event_id_generator: IDGenerator,
|
|
738
|
+
function_id_generator: IDGenerator,
|
|
739
|
+
tmp_generator: TmpGenerator,
|
|
740
|
+
**kwargs,
|
|
741
|
+
):
|
|
742
|
+
super().__init__(
|
|
743
|
+
language,
|
|
744
|
+
event_id_generator,
|
|
745
|
+
function_id_generator,
|
|
746
|
+
tmp_generator,
|
|
747
|
+
order=1,
|
|
748
|
+
**kwargs,
|
|
749
|
+
)
|
|
750
|
+
|
|
606
751
|
def get_function(self):
|
|
607
752
|
return "add_loop_end_event"
|
|
608
753
|
|
|
@@ -717,6 +862,7 @@ class UseEventFactory(PythonEventFactory):
|
|
|
717
862
|
return self._get_try_wrapper(event)
|
|
718
863
|
|
|
719
864
|
def get_event(self, node: AST, use: str) -> UseEvent:
|
|
865
|
+
# noinspection PyUnresolvedReferences
|
|
720
866
|
return UseEvent(
|
|
721
867
|
self.file, node.lineno, self.event_id_generator.get_next_id(), use
|
|
722
868
|
)
|
|
@@ -894,6 +1040,23 @@ class LenEventFactory(DefEventFactory):
|
|
|
894
1040
|
|
|
895
1041
|
|
|
896
1042
|
class TestStartEventFactory(FunctionEventFactory):
|
|
1043
|
+
def __init__(
|
|
1044
|
+
self,
|
|
1045
|
+
language,
|
|
1046
|
+
event_id_generator: IDGenerator,
|
|
1047
|
+
function_id_generator: IDGenerator,
|
|
1048
|
+
tmp_generator: TmpGenerator,
|
|
1049
|
+
**kwargs,
|
|
1050
|
+
):
|
|
1051
|
+
super().__init__(
|
|
1052
|
+
language,
|
|
1053
|
+
event_id_generator,
|
|
1054
|
+
function_id_generator,
|
|
1055
|
+
tmp_generator,
|
|
1056
|
+
order=2,
|
|
1057
|
+
**kwargs,
|
|
1058
|
+
)
|
|
1059
|
+
|
|
897
1060
|
def get_function(self):
|
|
898
1061
|
return "add_test_start_event"
|
|
899
1062
|
|
|
@@ -924,6 +1087,23 @@ class TestStartEventFactory(FunctionEventFactory):
|
|
|
924
1087
|
|
|
925
1088
|
|
|
926
1089
|
class TestEndEventFactory(FunctionEventFactory):
|
|
1090
|
+
def __init__(
|
|
1091
|
+
self,
|
|
1092
|
+
language,
|
|
1093
|
+
event_id_generator: IDGenerator,
|
|
1094
|
+
function_id_generator: IDGenerator,
|
|
1095
|
+
tmp_generator: TmpGenerator,
|
|
1096
|
+
**kwargs,
|
|
1097
|
+
):
|
|
1098
|
+
super().__init__(
|
|
1099
|
+
language,
|
|
1100
|
+
event_id_generator,
|
|
1101
|
+
function_id_generator,
|
|
1102
|
+
tmp_generator,
|
|
1103
|
+
order=2,
|
|
1104
|
+
**kwargs,
|
|
1105
|
+
)
|
|
1106
|
+
|
|
927
1107
|
def get_function(self):
|
|
928
1108
|
return "add_test_end_event"
|
|
929
1109
|
|
|
@@ -991,6 +1171,7 @@ class TestLineEventFactory(LineEventFactory):
|
|
|
991
1171
|
return "add_test_line_event"
|
|
992
1172
|
|
|
993
1173
|
def visit_line(self, node: AST) -> Injection:
|
|
1174
|
+
# noinspection PyUnresolvedReferences
|
|
994
1175
|
line_event = TestLineEvent(
|
|
995
1176
|
self.file, node.lineno, self.event_id_generator.get_next_id()
|
|
996
1177
|
)
|
|
@@ -1113,6 +1294,7 @@ class TestUseEventFactory(UseEventFactory):
|
|
|
1113
1294
|
return "add_test_use_event"
|
|
1114
1295
|
|
|
1115
1296
|
def get_event(self, node: AST, use: str) -> TestUseEvent:
|
|
1297
|
+
# noinspection PyUnresolvedReferences
|
|
1116
1298
|
return TestUseEvent(
|
|
1117
1299
|
self.file, node.lineno, self.event_id_generator.get_next_id(), use
|
|
1118
1300
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from abc import abstractmethod, ABC
|
|
2
3
|
|
|
3
4
|
from sflkit.language.meta import MetaVisitor
|
|
@@ -22,7 +23,7 @@ class ASTVisitor(ABC):
|
|
|
22
23
|
def start_visit(self, ast):
|
|
23
24
|
raise NotImplementedError()
|
|
24
25
|
|
|
25
|
-
def instrument(self, src:
|
|
26
|
+
def instrument(self, src: os.PathLike, dst: os.PathLike, file: str = ""):
|
|
26
27
|
self.file = file
|
|
27
28
|
with open(src, "r") as fp:
|
|
28
29
|
source = fp.read()
|