Skip to content

Commit 3362e51

Browse files
authored
feat(parser): add AST manipulation functions for inserting, replacing, and exporting AST as JSON (#24)
* Add convert_ast_to_estree * Add estree function and tests inside elixir part * Add insert_ast_at_index and replace_ast_at_index rust * Add some docs for rust functions * Update formatter.rs * Add nif functions * Add functions insert_at_index and replace_at_index inside elixir without testing * Add some tests * Change indexing of insert_at_index function * Update ast.rs * Delete -1 from docs
1 parent e7e28b8 commit 3362e51

File tree

12 files changed

+1131
-11
lines changed

12 files changed

+1131
-11
lines changed

lib/igniter_js/native.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ defmodule IgniterJs.Native do
5353

5454
def format_css_nif(_file_content), do: error()
5555

56+
def convert_ast_to_estree_nif(_file_content), do: error()
57+
58+
def insert_ast_at_index_nif(_file_content, _insert_code, _index), do: error()
59+
60+
def replace_ast_at_index_nif(_file_content, _replace_code, _index), do: error()
61+
5662
def is_css_formatted_nif(_file_content), do: error()
5763

5864
defp error, do: :erlang.nif_error(:nif_not_loaded)

lib/igniter_js/parsers/javascript/parser.ex

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,4 +295,109 @@ defmodule IgniterJs.Parsers.Javascript.Parser do
295295
type
296296
)
297297
end
298+
299+
@doc """
300+
Converts a JavaScript AST into the ESTree format.
301+
302+
This function takes either a file path or raw JavaScript content, processes it
303+
and returns the resulting ESTree Map structure.
304+
305+
```elixir
306+
alias IgniterJs.Parsers.Javascript.Parser
307+
Parser.ast_to_estree(js_content)
308+
Parser.ast_to_estree("/path/to/file.js", :path)
309+
```
310+
"""
311+
def ast_to_estree(file_path_or_content, type \\ :content) do
312+
call_nif_fn(
313+
file_path_or_content,
314+
__ENV__.function,
315+
fn file_content ->
316+
Native.convert_ast_to_estree_nif(file_content)
317+
end,
318+
type
319+
)
320+
|> case do
321+
{:ok, _, output} ->
322+
{:ok, :ast_to_estree, Jason.decode!(output)}
323+
324+
{:error, :ast_to_estree, error} ->
325+
{:error, :ast_to_estree, error}
326+
end
327+
end
328+
329+
@doc """
330+
Inserts a JavaScript AST at the specified index within an existing AST.
331+
332+
This function takes either a file path or raw JavaScript content, along with the
333+
JavaScript code to be inserted and the target index. It processes the AST and inserts
334+
the new code at the specified position.
335+
336+
337+
```elixir
338+
alias IgniterJs.Parsers.Javascript.Parser
339+
340+
# Insert after index 1
341+
Parser.insert_at_index(js_content, "function newFunc() {}", 1)
342+
343+
# Insert before all code
344+
Parser.insert_at_index(js_content, "function newFunc() {}", 0)
345+
346+
# Insert using a file path
347+
Parser.insert_at_index("/path/to/file.js", "function newFunc() {}", 2, :path)
348+
```
349+
"""
350+
def insert_at_index(
351+
file_path_or_content,
352+
insert_code,
353+
index,
354+
type \\ :content
355+
) do
356+
call_nif_fn(
357+
file_path_or_content,
358+
__ENV__.function,
359+
fn file_content ->
360+
Native.insert_ast_at_index_nif(file_content, insert_code, index)
361+
end,
362+
type
363+
)
364+
end
365+
366+
@doc """
367+
Replaces a JavaScript AST node at the specified index with new JavaScript code.
368+
369+
This function takes either a file path or raw JavaScript content, along with the
370+
JavaScript code that should replace an existing node at the given index. It processes
371+
the AST and replaces the target node while preserving the surrounding structure.
372+
373+
If the `index` is out of bounds, an error is returned.
374+
375+
```elixir
376+
alias IgniterJs.Parsers.Javascript.Parser
377+
378+
# Replace node at index 1
379+
Parser.replace_at_index(js_content, "function newFunc() {}", 1)
380+
381+
# Replace node at index 0 (first item)
382+
Parser.replace_at_index(js_content, "function newFunc() {}", 0)
383+
384+
# Replace using a file path
385+
Parser.replace_at_index("/path/to/file.js", "function newFunc() {}", 2, :path)
386+
```
387+
"""
388+
def replace_at_index(
389+
file_path_or_content,
390+
replace_code,
391+
index,
392+
type \\ :content
393+
) do
394+
call_nif_fn(
395+
file_path_or_content,
396+
__ENV__.function,
397+
fn file_content ->
398+
Native.replace_ast_at_index_nif(file_content, replace_code, index)
399+
end,
400+
type
401+
)
402+
end
298403
end

mix.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ defmodule IgniterJs.MixProject do
106106
defp deps do
107107
[
108108
{:rustler, "~> 0.36.1", optional: true},
109+
{:jason, "~> 1.4"},
109110
{:rustler_precompiled, "~> 0.8"},
110111
{:ex_doc, "~> 0.35", only: [:dev, :test], runtime: false},
111112
{:ex_check, "~> 0.12", only: [:dev, :test]},

0 commit comments

Comments
 (0)