View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.ecmascript.ast;
5   
6   import java.util.Arrays;
7   
8   /**
9    * Calculates from an absolute offset in the source file the line/column coordinate.
10   * This is needed as Rhino only offers absolute positions for each node.
11   * 
12   * Idea from: http://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/javascript/jscomp/SourceFile.java
13   */
14  public class SourceCodePositioner {
15  
16      private int[] lineOffsets;
17      
18      public SourceCodePositioner(String sourceCode) {
19  	analyzeLineOffsets(sourceCode);
20      }
21  
22      private void analyzeLineOffsets(String sourceCode) {
23  	String[] lines = sourceCode.split("\n");
24  	
25  	int startOffset = 0;
26  	int lineNumber = 0;
27  	
28  	lineOffsets = new int[lines.length];
29  	
30  	for (String line : lines) {
31  	    lineOffsets[lineNumber] = startOffset;
32  	    lineNumber++;
33  	    startOffset += line.length() + 1; // +1 for the "\n" character
34  	}
35      }
36  
37      public int lineNumberFromOffset(int offset) {
38  	int search = Arrays.binarySearch(lineOffsets, offset);
39  	int lineNumber;
40  	if (search >= 0) {
41  	    lineNumber = search;
42  	} else {
43  	    int insertionPoint = search;
44  	    insertionPoint += 1;
45  	    insertionPoint *= -1;
46  	    lineNumber = insertionPoint - 1; // take the insertion point one before
47  	}
48  	return lineNumber + 1; // 1-based line numbers
49      }
50      
51      public int columnFromOffset(int offset) {
52  	int lineNumber = lineNumberFromOffset(offset);
53  	int columnOffset = offset - lineOffsets[lineNumber - 1];
54  	return columnOffset + 1; // 1-based column offsets
55      }
56  }