File size: 6,466 Bytes
7a21841
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import os
import re
import sys
from graphviz import Digraph
import esprima

def detect_file_dependencies(root_dir):
    """

    Menelusuri semua file dalam root_dir dan mendeteksi dependency sederhana.

    Jika sebuah file (HTML) menautkan file lain (JS/CSS) melalui tag <script> atau <link>,

    maka dependency tersebut dicatat.

    """
    dep_graph = {}
    for subdir, _, files in os.walk(root_dir):
        for file in files:
            ext = os.path.splitext(file)[1].lower()
            if ext in ['.html', '.js', '.css']:
                filepath = os.path.join(subdir, file)
                try:
                    with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
                        content = f.read()
                except Exception as e:
                    print(f"Error reading {filepath}: {e}")
                    continue

                dependencies = []
                if ext == '.html':
                    scripts = re.findall(r'<script\s+[^>]*src=["\'](.*?)["\']', content, re.IGNORECASE)
                    links = re.findall(r'<link\s+[^>]*href=["\'](.*?)["\']', content, re.IGNORECASE)
                    dependencies.extend(scripts)
                    dependencies.extend(links)
                dep_graph[filepath] = dependencies
    return dep_graph

def build_file_dependency_flowchart(dep_graph, output_file='results/project_file_dependencies'):
    """

    Membuat diagram flowchart dependency antar file menggunakan Graphviz.

    Jika string dependency (misalnya, 'script.js') ditemukan dalam nama file lain, dibuat edge.

    """
    dot = Digraph(comment='Project File Dependencies')
    for file in dep_graph:
        dot.node(file, os.path.basename(file))
    for file, deps in dep_graph.items():
        for dep in deps:
            for candidate in dep_graph:
                if dep in os.path.basename(candidate):
                    dot.edge(file, candidate)
    dot.render(output_file, view=True)
    print(f"Diagram dependency file disimpan sebagai {output_file}.pdf")

def generate_full_js_flowchart(js_file):
    """

    Menghasilkan flowchart yang mencoba mengidentifikasi seluruh _syntax_ yang mempengaruhi

    alur kontrol pada file JavaScript dengan mengurai AST menggunakan esprima.

    Node-node yang dihasilkan mencakup FunctionDeclaration, IfStatement, loop, SwitchStatement,

    ReturnStatement, CallExpression, dan jenis node lainnya.

    """
    try:
        with open(js_file, 'r', encoding='utf-8') as f:
            code = f.read()
    except Exception as e:
        print(f"Error reading {js_file}: {e}")
        return None

    try:
        ast = esprima.parseScript(code, tolerant=True)
    except Exception as e:
        print(f"Error parsing {js_file}: {e}")
        return None

    flowchart = Digraph(comment=f'Full JS Flowchart: {os.path.basename(js_file)}')
    node_counter = 0

    def new_node(label):
        nonlocal node_counter
        node_id = f"node{node_counter}"
        node_counter += 1
        flowchart.node(node_id, label)
        return node_id

    def traverse_full(node, parent_node=None):
        if isinstance(node, dict):
            node_type = node.get('type')
            current_node = None

            if node_type == 'FunctionDeclaration':
                func_name = node.get('id', {}).get('name', 'anonymous')
                current_node = new_node(f'Function: {func_name}')
            elif node_type == 'IfStatement':
                current_node = new_node('If Statement')
            elif node_type in ['ForStatement', 'WhileStatement', 'DoWhileStatement']:
                current_node = new_node(node_type)
            elif node_type == 'SwitchStatement':
                current_node = new_node('Switch Statement')
            elif node_type == 'ReturnStatement':
                current_node = new_node('Return')
            elif node_type == 'CallExpression':
                callee = node.get('callee')
                if callee and callee.get('type') == 'Identifier':
                    current_node = new_node(f'Call: {callee.get("name")}')

            else:

                current_node = new_node(node_type)

            if parent_node and current_node:
                flowchart.edge(parent_node, current_node)
            new_parent = current_node if current_node else parent_node
            for key, value in node.items():

                if key in ['loc', 'range', 'raw']:
                    continue
                traverse_full(value, parent_node=new_parent)
        elif isinstance(node, list):
            for item in node:
                traverse_full(item, parent_node=parent_node)

    traverse_full(ast.toDict(), parent_node=None)
    return flowchart

def build_all_full_js_flowcharts(root_dir, output_folder='results/full_js_flowcharts'):
    """

    Menelusuri seluruh file dalam root_dir, dan untuk setiap file JS menghasilkan flowchart

    lengkap dari seluruh syntax yang mempengaruhi alur. Flowchart disimpan di output_folder.

    """
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    for subdir, _, files in os.walk(root_dir):
        for file in files:
            ext = os.path.splitext(file)[1].lower()
            if ext == '.js':
                js_file = os.path.join(subdir, file)
                print(f"Memproses {js_file} untuk flowchart lengkap...")
                flowchart = generate_full_js_flowchart(js_file)
                if flowchart:
                    base_name = os.path.splitext(os.path.basename(js_file))[0]
                    output_name = os.path.join(output_folder, base_name + '_full_flowchart')
                    flowchart.render(output_name, view=False)
                    print(f"Flowchart lengkap untuk {js_file} disimpan sebagai {output_name}.pdf")

if __name__ == '__main__':
    root_directory = '/content/drive/MyDrive/Developer/Project/Competition/Alhazen Coding Quest 20 Days Ramadhan Challenge/FINAL PROJECT'

    dependency_graph = detect_file_dependencies(root_directory)
    print("Dependency Graph Antar File:")
    for file, deps in dependency_graph.items():
        print(f"{file}: {deps}")
    build_file_dependency_flowchart(dependency_graph)

    build_all_full_js_flowcharts(root_directory)

    sys.stdout.flush()
    input("Tekan Enter untuk keluar...")