1package org.chromium.devtools.jsdoc; 2 3import com.google.javascript.jscomp.SourceFile; 4import com.google.javascript.rhino.Node; 5 6import java.io.IOException; 7import java.util.Collections; 8import java.util.Comparator; 9import java.util.SortedSet; 10import java.util.TreeSet; 11 12public class ValidatorContext { 13 14 private static final Comparator<MessageRecord> MESSAGE_RECORD_COMPARATOR = 15 new Comparator<MessageRecord>() { 16 @Override 17 public int compare(MessageRecord left, MessageRecord right) { 18 return left.position - right.position; 19 } 20 }; 21 22 public final String scriptFileName; 23 public final SourceFile sourceFile; 24 private final SortedSet<MessageRecord> validationResult = 25 new TreeSet<>(MESSAGE_RECORD_COMPARATOR); 26 27 28 public ValidatorContext(String text, String scriptFileName) { 29 this.scriptFileName = scriptFileName; 30 this.sourceFile = SourceFile.builder().buildFromCode(scriptFileName, text); 31 } 32 33 public SortedSet<MessageRecord> getValidationResult() { 34 return Collections.unmodifiableSortedSet(validationResult); 35 } 36 37 public String getNodeText(Node node) { 38 if (node == null) { 39 return null; 40 } 41 try { 42 return sourceFile.getCode().substring( 43 node.getSourceOffset(), node.getSourceOffset() + node.getLength()); 44 } catch (IOException e) { 45 return null; 46 } 47 } 48 49 public SourcePosition getPosition(int offset) { 50 return new SourcePosition( 51 sourceFile.getLineOfOffset(offset), sourceFile.getColumnOfOffset(offset)); 52 } 53 54 public void reportErrorInNode(Node node, int offsetInNodeText, String errorText) { 55 int errorAbsoluteOffset = node.getSourceOffset() + offsetInNodeText; 56 reportErrorAtOffset(errorAbsoluteOffset, errorText); 57 } 58 59 public void reportErrorAtOffset(int offset, String errorText) { 60 SourcePosition position = getPosition(offset); 61 StringBuilder positionMarker = new StringBuilder(position.column + 1); 62 for (int i = position.column; i > 0; --i) { 63 positionMarker.append(' '); 64 } 65 positionMarker.append('^'); 66 String message = String.format("%s:%d: ERROR - %s%n%s%n%s%n", 67 scriptFileName, 68 position.line, 69 errorText, 70 sourceFile.getLine(position.line), 71 positionMarker.toString()); 72 validationResult.add(new MessageRecord(offset, message)); 73 } 74 75 public static class MessageRecord { 76 public final int position; 77 public final String text; 78 79 public MessageRecord(int position, String text) { 80 this.position = position; 81 this.text = text; 82 } 83 } 84 85 public static class SourcePosition { 86 public final int line; 87 public final int column; 88 89 public SourcePosition(int line, int column) { 90 this.line = line; 91 this.column = column; 92 } 93 } 94} 95