Skip to content

Commit

Permalink
Make RootNode of AST know whether it requires coverage or not.
Browse files Browse the repository at this point in the history
This is infrastructure work and not a full fix for #1196.  I
kept this separate in case we decide to fix 1.7.x as the rest
of the fixes will be in IR (which 1.7 lacks).
  • Loading branch information
enebo committed Mar 23, 2016
1 parent 89f4c06 commit 39d35c0
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 27 deletions.
19 changes: 15 additions & 4 deletions core/src/main/java/org/jruby/ast/RootNode.java
Expand Up @@ -31,6 +31,7 @@
import java.util.List;

import org.jruby.ast.visitor.NodeVisitor;
import org.jruby.ext.coverage.CoverageData;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
Expand All @@ -49,21 +50,26 @@ public class RootNode extends Node {
private Node bodyNode;
private String file;
private int endPosition;
private boolean needsCodeCoverage;

public RootNode(ISourcePosition position, DynamicScope scope, Node bodyNode, String file) {
this(position, scope, bodyNode, file, -1);
this(position, scope, bodyNode, file, -1, false);
}

public RootNode(ISourcePosition position, DynamicScope scope, Node bodyNode, String file, int endPosition) {
public RootNode(ISourcePosition position, DynamicScope scope, Node bodyNode, String file, int endPosition, boolean needsCodeCoverage) {
super(position, bodyNode.containsVariableAssignment());

assert bodyNode != null : "bodyNode is not null";

this.scope = scope;
this.staticScope = scope.getStaticScope();
this.bodyNode = bodyNode;
this.file = file;
this.endPosition = endPosition;
this.needsCodeCoverage = needsCodeCoverage;
}

@Deprecated
public RootNode(ISourcePosition position, DynamicScope scope, Node bodyNode, String file, int endPosition) {
this(position, scope, bodyNode, file, endPosition, false);
}

public NodeType getNodeType() {
Expand Down Expand Up @@ -122,4 +128,9 @@ public boolean hasEndPosition() {
public int getEndPosition() {
return endPosition;
}

// Is coverage enabled and is this a valid source file for coverage to apply?
public boolean needsCoverage() {
return needsCodeCoverage;
}
}
6 changes: 0 additions & 6 deletions core/src/main/java/org/jruby/parser/Parser.java
Expand Up @@ -158,12 +158,6 @@ public Node parse(String file, LexerSource lexerSource, DynamicScope blockScope,
totalTime += System.nanoTime() - startTime;
totalBytes += lexerSource.getOffset();

// set coverage baseline into coverage data
if (!configuration.isEvalParse() && runtime.getCoverageData().isCoverageEnabled()) {
configuration.growCoverageLines(parser.lexer.lineno());
runtime.getCoverageData().prepareCoverage(file, configuration.getCoverage());
}

return ast;
}

Expand Down
25 changes: 22 additions & 3 deletions core/src/main/java/org/jruby/parser/ParserConfiguration.java
Expand Up @@ -34,6 +34,7 @@
import org.jcodings.specific.UTF8Encoding;
import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.ext.coverage.CoverageData;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.encoding.EncodingService;
import org.jruby.runtime.scope.ManyVarsDynamicScope;
Expand Down Expand Up @@ -85,7 +86,6 @@ public ParserConfiguration(Ruby runtime, int lineNumber,
this.frozenStringLiteral = config.isFrozenStringLiteral();
}


public void setFrozenStringLiteral(boolean frozenStringLiteral) {
this.frozenStringLiteral = frozenStringLiteral;
}
Expand Down Expand Up @@ -162,7 +162,11 @@ public DynamicScope getScope(String file) {
// any of the specific-size scopes.
return new ManyVarsDynamicScope(runtime.getStaticScopeFactory().newLocalScope(null, file), existingScope);
}


public boolean isCoverageEnabled() {
return !isEvalParse() && runtime.getCoverageData().isCoverageEnabled();
}

/**
* Get whether we are saving the DATA contents of the file.
*/
Expand All @@ -185,7 +189,7 @@ public boolean isInlineSource() {
public void coverLine(int i) {
if (i < 0) return; // JRUBY-6868: why would there be negative line numbers?

if (!isEvalParse() && runtime.getCoverageData().isCoverageEnabled()) {
if (!isCoverageEnabled()) {
growCoverageLines(i);
coverage[i] = 0;
}
Expand All @@ -207,9 +211,24 @@ public void growCoverageLines(int i) {
}
}

/**
* At end of a parse if coverage is enabled we will do final processing
* of the primitive coverage array and make sure runtimes coverage data
* has been updated with this new data.
*/
public CoverageData finishCoverage(String file, int lines) {
if (!isCoverageEnabled()) return null;

growCoverageLines(lines);
CoverageData data = runtime.getCoverageData();
data.prepareCoverage(file, coverage);
return data;
}

/**
* Get the coverage array, indicating all coverable lines
*/
@Deprecated
public int[] getCoverage() {
return coverage;
}
Expand Down
30 changes: 16 additions & 14 deletions core/src/main/java/org/jruby/parser/ParserSupport.java
Expand Up @@ -47,6 +47,7 @@
import org.jruby.common.IRubyWarnings;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.exceptions.RaiseException;
import org.jruby.ext.coverage.CoverageData;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.lexer.yacc.ISourcePositionHolder;
import org.jruby.lexer.yacc.RubyLexer;
Expand Down Expand Up @@ -85,7 +86,7 @@ public void reset() {
inSingleton = 0;
inDefinition = false;
}

public StaticScope getCurrentScope() {
return currentScope;
}
Expand Down Expand Up @@ -188,7 +189,8 @@ public Node newline_node(Node node, ISourcePosition position) {

return node;
}


// This is the last node made in the AST unintuitively so so post-processing can occur here.
public Node addRootNode(Node topOfAST) {
final int endPosition;

Expand All @@ -198,28 +200,28 @@ public Node addRootNode(Node topOfAST) {
endPosition = -1;
}

ISourcePosition position;
CoverageData coverageData = configuration.finishCoverage(lexer.getFile(), lexer.lineno());
if (result.getBeginNodes().isEmpty()) {
ISourcePosition position;
if (topOfAST == null) {
topOfAST = NilImplicitNode.NIL;
position = lexer.getPosition();
} else {
position = topOfAST.getPosition();
}

return new RootNode(position, result.getScope(), topOfAST, lexer.getFile(), endPosition);
}
} else {
position = topOfAST != null ? topOfAST.getPosition() : result.getBeginNodes().get(0).getPosition();
BlockNode newTopOfAST = new BlockNode(position);
for (Node beginNode : result.getBeginNodes()) {
appendToBlock(newTopOfAST, beginNode);
}

ISourcePosition position = topOfAST != null ? topOfAST.getPosition() : result.getBeginNodes().get(0).getPosition();
BlockNode newTopOfAST = new BlockNode(position);
for (Node beginNode: result.getBeginNodes()) {
appendToBlock(newTopOfAST, beginNode);
// Add real top to new top (unless this top is empty [only begin/end nodes or truly empty])
if (topOfAST != null) newTopOfAST.add(topOfAST);
topOfAST = newTopOfAST;
}

// Add real top to new top (unless this top is empty [only begin/end nodes or truly empty])
if (topOfAST != null) newTopOfAST.add(topOfAST);

return new RootNode(position, result.getScope(), newTopOfAST, lexer.getFile(), endPosition);
return new RootNode(position, result.getScope(), topOfAST, lexer.getFile(), endPosition, coverageData != null);
}

/* MRI: block_append */
Expand Down

0 comments on commit 39d35c0

Please sign in to comment.