Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ Metrics/CyclomaticComplexity:
- lib/herb/ast/nodes.rb
- lib/herb/cli.rb
- lib/herb/engine.rb
- lib/herb/prism_inspect.rb
- lib/herb/engine/**/*.rb
- templates/template.rb

Metrics/MethodLength:
Max: 20
Expand All @@ -68,6 +70,7 @@ Metrics/MethodLength:
- lib/herb/project.rb
- lib/herb/engine.rb
- lib/herb/engine/**/*.rb
- lib/herb/prism_inspect.rb
- templates/template.rb
- test/fork_helper.rb
- test/snapshot_utils.rb
Expand All @@ -83,6 +86,7 @@ Metrics/AbcSize:
- lib/herb/engine.rb
- lib/herb/engine/**/*.rb
- lib/herb/token.rb
- lib/herb/prism_inspect.rb
- templates/template.rb
- test/fork_helper.rb
- test/snapshot_utils.rb
Expand All @@ -98,6 +102,7 @@ Metrics/ClassLength:
- lib/herb/engine/**/*.rb
- lib/herb/project.rb
- lib/herb/visitor.rb
- lib/herb/ast/nodes.rb
- test/**/*_test.rb

Metrics/ModuleLength:
Expand All @@ -121,14 +126,17 @@ Metrics/ParameterLists:
Exclude:
- lib/herb/ast/node.rb
- lib/herb/ast/nodes.rb
- lib/herb/errors.rb
- lib/herb/engine/validators/security_validator.rb
- lib/herb/errors.rb
- lib/herb/parser_options.rb
- lib/herb/prism_inspect.rb

Metrics/PerceivedComplexity:
Exclude:
- lib/herb/ast/nodes.rb
- lib/herb/cli.rb
- lib/herb/project.rb
- lib/herb/prism_inspect.rb
- lib/herb/engine.rb
- lib/herb/engine/**/*.rb
- templates/template.rb
Expand Down
36 changes: 36 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,12 @@ nodes:
type: array
kind: Node

- name: prism_context
type: prism_context

- name: prism_node
type: prism_node

- name: LiteralNode
fields:
- name: content
Expand Down Expand Up @@ -643,6 +649,9 @@ nodes:
- name: valid
type: boolean

- name: prism_node
type: prism_node

- name: ERBEndNode
fields:
- name: tag_opening
Expand Down Expand Up @@ -686,6 +695,9 @@ nodes:
# - name: predicate
# type: prism_node

- name: prism_node
type: prism_node

- name: statements
type: array
kind: Node
Expand Down Expand Up @@ -717,6 +729,9 @@ nodes:
# - name: opener
# type: prism_node

- name: prism_node
type: prism_node

- name: body
type: array
kind: Node
Expand Down Expand Up @@ -765,6 +780,9 @@ nodes:
# - name: predicate
# type: prism_node

- name: prism_node
type: prism_node

- name: conditions
type: array
kind: ERBWhenNode
Expand Down Expand Up @@ -795,6 +813,9 @@ nodes:
# - name: predicate
# type: prism_node

- name: prism_node
type: prism_node

- name: conditions
type: array
kind: ERBInNode
Expand All @@ -821,6 +842,9 @@ nodes:
# - name: predicate
# type: prism_node

- name: prism_node
type: prism_node

- name: statements
type: array
kind: Node
Expand All @@ -843,6 +867,9 @@ nodes:
# - name: predicate
# type: prism_node

- name: prism_node
type: prism_node

- name: statements
type: array
kind: Node
Expand All @@ -868,6 +895,9 @@ nodes:
# - name: collection
# type: prism_node

- name: prism_node
type: prism_node

- name: statements
type: array
kind: Node
Expand Down Expand Up @@ -928,6 +958,9 @@ nodes:
- name: tag_closing
type: token

- name: prism_node
type: prism_node

- name: statements
type: array
kind: Node
Expand Down Expand Up @@ -965,6 +998,9 @@ nodes:
# - name: predicate
# type: prism_node

- name: prism_node
type: prism_node

- name: statements
type: array
kind: Node
Expand Down
1 change: 0 additions & 1 deletion ext/herb/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
$CFLAGS << " -DPRISM_EXCLUDE_PRETTYPRINT"
$CFLAGS << " -DPRISM_EXCLUDE_JSON"
$CFLAGS << " -DPRISM_EXCLUDE_PACK"
$CFLAGS << " -DPRISM_EXCLUDE_SERIALIZATION"

herb_src_files = Dir.glob("#{$srcdir}/../../src/**/*.c").map { |file| file.delete_prefix("../../../../ext/herb/") }.sort

Expand Down
12 changes: 12 additions & 0 deletions ext/herb/extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,18 @@ static VALUE Herb_parse(int argc, VALUE* argv, VALUE self) {
}
if (!NIL_P(action_view_helpers) && RTEST(action_view_helpers)) { parser_options.action_view_helpers = true; }

VALUE prism_nodes = rb_hash_lookup(options, rb_utf8_str_new_cstr("prism_nodes"));
if (NIL_P(prism_nodes)) { prism_nodes = rb_hash_lookup(options, ID2SYM(rb_intern("prism_nodes"))); }
if (!NIL_P(prism_nodes) && RTEST(prism_nodes)) { parser_options.prism_nodes = true; }

VALUE prism_nodes_deep = rb_hash_lookup(options, rb_utf8_str_new_cstr("prism_nodes_deep"));
if (NIL_P(prism_nodes_deep)) { prism_nodes_deep = rb_hash_lookup(options, ID2SYM(rb_intern("prism_nodes_deep"))); }
if (!NIL_P(prism_nodes_deep) && RTEST(prism_nodes_deep)) { parser_options.prism_nodes_deep = true; }

VALUE prism_program = rb_hash_lookup(options, rb_utf8_str_new_cstr("prism_program"));
if (NIL_P(prism_program)) { prism_program = rb_hash_lookup(options, ID2SYM(rb_intern("prism_program"))); }
if (!NIL_P(prism_program) && RTEST(prism_program)) { parser_options.prism_program = true; }

VALUE arena_stats = rb_hash_lookup(options, rb_utf8_str_new_cstr("arena_stats"));
if (NIL_P(arena_stats)) { arena_stats = rb_hash_lookup(options, ID2SYM(rb_intern("arena_stats"))); }
if (!NIL_P(arena_stats) && RTEST(arena_stats)) { print_arena_stats = true; }
Expand Down
3 changes: 3 additions & 0 deletions ext/herb/extension_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ VALUE create_parse_result(AST_DOCUMENT_NODE_T* root, VALUE source, const parser_
rb_hash_aset(kwargs, ID2SYM(rb_intern("track_whitespace")), options->track_whitespace ? Qtrue : Qfalse);
rb_hash_aset(kwargs, ID2SYM(rb_intern("analyze")), options->analyze ? Qtrue : Qfalse);
rb_hash_aset(kwargs, ID2SYM(rb_intern("action_view_helpers")), options->action_view_helpers ? Qtrue : Qfalse);
rb_hash_aset(kwargs, ID2SYM(rb_intern("prism_nodes")), options->prism_nodes ? Qtrue : Qfalse);
rb_hash_aset(kwargs, ID2SYM(rb_intern("prism_nodes_deep")), options->prism_nodes_deep ? Qtrue : Qfalse);
rb_hash_aset(kwargs, ID2SYM(rb_intern("prism_program")), options->prism_program ? Qtrue : Qfalse);

VALUE parser_options_args[1] = { kwargs };
VALUE parser_options = rb_class_new_instance_kw(1, parser_options_args, cParserOptions, RB_PASS_KEYWORDS);
Expand Down
2 changes: 1 addition & 1 deletion java/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ PRISM_BUILD = $(PRISM_PATH)/build

JAVAC = $(JAVA_HOME)/bin/javac
JAVA_CMD = $(JAVA_HOME)/bin/java
CFLAGS = -std=c99 -Wall -Wextra -fPIC -O2 -DHERB_EXCLUDE_PRETTYPRINT -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXCLUDE_JSON -DPRISM_EXCLUDE_PACK -DPRISM_EXCLUDE_SERIALIZATION
CFLAGS = -std=c99 -Wall -Wextra -fPIC -O2 -DHERB_EXCLUDE_PRETTYPRINT -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXCLUDE_JSON -DPRISM_EXCLUDE_PACK
INCLUDES = -I. -I$(SRC_DIR)/include -I$(PRISM_INCLUDE) $(JNI_INCLUDES)
LDFLAGS = -shared
LIBS = $(PRISM_BUILD)/libprism.a
Expand Down
24 changes: 24 additions & 0 deletions java/herb_jni.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,30 @@ Java_org_herb_Herb_parse(JNIEnv* env, jclass clazz, jstring source, jobject opti
jboolean actionViewHelpers = (*env)->CallBooleanMethod(env, options, getActionViewHelpers);
parser_options.action_view_helpers = (actionViewHelpers == JNI_TRUE);
}

jmethodID getPrismNodes =
(*env)->GetMethodID(env, optionsClass, "isPrismNodes", "()Z");

if (getPrismNodes != NULL) {
jboolean prismNodes = (*env)->CallBooleanMethod(env, options, getPrismNodes);
parser_options.prism_nodes = (prismNodes == JNI_TRUE);
}

jmethodID getPrismNodesDeep =
(*env)->GetMethodID(env, optionsClass, "isPrismNodesDeep", "()Z");

if (getPrismNodesDeep != NULL) {
jboolean prismNodesDeep = (*env)->CallBooleanMethod(env, options, getPrismNodesDeep);
parser_options.prism_nodes_deep = (prismNodesDeep == JNI_TRUE);
}

jmethodID getPrismProgram =
(*env)->GetMethodID(env, optionsClass, "isPrismProgram", "()Z");

if (getPrismProgram != NULL) {
jboolean prismProgram = (*env)->CallBooleanMethod(env, options, getPrismProgram);
parser_options.prism_program = (prismProgram == JNI_TRUE);
}
}

hb_allocator_T allocator;
Expand Down
45 changes: 45 additions & 0 deletions java/org/herb/HerbTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,51 @@ void testParserOptionsTrackWhitespace() {
assertFalse(inspectWithout.contains("WhitespaceNode"));
}

@Test
void testParserOptionsPrismNodes() {
String source = "<%= user.name %>";

ParseResult withPrism = Herb.parse(source, ParserOptions.create().prismNodes(true));
String inspected = withPrism.inspect();

assertTrue(inspected.contains("prism_node:"));
}

@Test
void testParserOptionsPrismNodesString() {
String source = "<%= \"String\" %>";

ParseResult withPrism = Herb.parse(source, ParserOptions.create().prismNodes(true));
String inspected = withPrism.inspect();

assertTrue(inspected.contains("prism_node:"));
assertTrue(inspected.contains("String"));
}

@Test
void testParserOptionsPrismProgram() {
String source = "<%= \"hello\" %>";

ParseResult withPrism = Herb.parse(source, ParserOptions.create().prismProgram(true));
String inspected = withPrism.inspect();

assertTrue(inspected.contains("prism_node:"));
}

@Test
void testParserOptionsPrismNodesDeep() {
String source = "<% if true %><%= \"yes\" %><% end %>";

ParseResult withDeep = Herb.parse(source, ParserOptions.create().prismNodes(true).prismNodesDeep(true));
ParseResult withoutDeep = Herb.parse(source, ParserOptions.create().prismNodes(true).prismNodesDeep(false));

String inspectDeep = withDeep.inspect();
String inspectShallow = withoutDeep.inspect();

assertTrue(inspectDeep.contains("prism_node:"));
assertTrue(inspectShallow.contains("prism_node:"));
}

@Test
void testParserOptionsAnalyze() {
String source = "<% if true %><div></div><% end %>";
Expand Down
2 changes: 1 addition & 1 deletion java/org/herb/ParseResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public String inspect() {
StringBuilder builder = new StringBuilder();

if (value != null) {
builder.append(value.inspect());
builder.append(value.inspect(source));
}

if (hasErrors()) {
Expand Down
30 changes: 30 additions & 0 deletions java/org/herb/ParserOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ public class ParserOptions {
private boolean analyze = true;
private boolean strict = true;
private boolean actionViewHelpers = false;
private boolean prismNodes = false;
private boolean prismNodesDeep = false;
private boolean prismProgram = false;

public ParserOptions() {}

Expand Down Expand Up @@ -44,6 +47,33 @@ public boolean isActionViewHelpers() {
return actionViewHelpers;
}

public ParserOptions prismNodes(boolean value) {
this.prismNodes = value;
return this;
}

public boolean isPrismNodes() {
return prismNodes;
}

public ParserOptions prismNodesDeep(boolean value) {
this.prismNodesDeep = value;
return this;
}

public boolean isPrismNodesDeep() {
return prismNodesDeep;
}

public ParserOptions prismProgram(boolean value) {
this.prismProgram = value;
return this;
}

public boolean isPrismProgram() {
return prismProgram;
}

public static ParserOptions create() {
return new ParserOptions();
}
Expand Down
23 changes: 21 additions & 2 deletions java/org/herb/ast/BaseNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public java.util.List<Node> getErrors() {
return errors;
}

@Override
public String inspect(String source) {
return inspect();
}

@Override
public <R, C> R accept(NodeVisitor<R, C> visitor, C context) {
return visitor.visitNode(this, context);
Expand Down Expand Up @@ -79,6 +84,13 @@ protected String inspectErrors(String prefix) {
* Helper to format an array of nodes for tree inspection.
*/
protected String inspectArray(java.util.List<Node> array, String prefix) {
return inspectArray(array, prefix, null);
}

/**
* Helper to format an array of nodes for tree inspection with source for Prism nodes.
*/
protected String inspectArray(java.util.List<Node> array, String prefix, String source) {
if (array == null) return "∅\n";
if (array.isEmpty()) return "[]\n";

Expand All @@ -92,7 +104,7 @@ protected String inspectArray(java.util.List<Node> array, String prefix) {
String nextPrefix = isLast ? " " : "│ ";

if (item != null) {
String tree = item.inspect();
String tree = source != null ? item.inspect(source) : item.inspect();

if (tree.endsWith("\n")) {
tree = tree.substring(0, tree.length() - 1);
Expand All @@ -119,8 +131,15 @@ protected String inspectArray(java.util.List<Node> array, String prefix) {
* Helper to format a single node for tree inspection.
*/
protected String inspectNode(Node node, String prefix) {
return inspectNode(node, prefix, null);
}

/**
* Helper to format a single node for tree inspection with source for Prism nodes.
*/
protected String inspectNode(Node node, String prefix, String source) {
if (node == null) return "∅\n";
String tree = node.inspect();
String tree = source != null ? node.inspect(source) : node.inspect();

if (tree.endsWith("\n")) {
tree = tree.substring(0, tree.length() - 1);
Expand Down
Loading
Loading