001: /*
002: * Spoon - http://spoon.gforge.inria.fr/
003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
004: *
005: * This software is governed by the CeCILL-C License under French law and
006: * abiding by the rules of distribution of free software. You can use, modify
007: * and/or redistribute the software under the terms of the CeCILL-C license as
008: * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
009: *
010: * This program is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
013: *
014: * The fact that you are presently reading this means that you have had
015: * knowledge of the CeCILL-C license and that you accept its terms.
016: */
017:
018: package spoon.support.reflect.cu;
019:
020: import java.io.File;
021: import java.io.Serializable;
022:
023: import spoon.reflect.cu.CompilationUnit;
024: import spoon.reflect.cu.SourcePosition;
025:
026: /**
027: * This class represents the position of a Java program element in a source
028: * file.
029: */
030:
031: public class SourcePositionImpl implements SourcePosition, Cloneable,
032: Serializable {
033:
034: private static final long serialVersionUID = 1L;
035:
036: /**
037: * Search the line number corresponding to a specific position
038: */
039: private int searchLineNumber(int[] startLineIndexes, int position) {
040: if (startLineIndexes == null)
041: return 1;
042: int length = startLineIndexes.length;
043: if (length == 0)
044: return 1;
045: int g = 0, d = length - 1;
046: int m = 0, start;
047: while (g <= d) {
048: m = (g + d) / 2;
049: if (position < (start = startLineIndexes[m])) {
050: d = m - 1;
051: } else if (position > start) {
052: g = m + 1;
053: } else {
054: return m + 1;
055: }
056: }
057: if (position < startLineIndexes[m]) {
058: return m + 1;
059: }
060: return m + 2;
061: }
062:
063: /**
064: * Search the column number
065: */
066: private int searchColumnNumber(int[] startLineIndexes, int position) {
067: if (startLineIndexes == null)
068: return 1;
069: int length = startLineIndexes.length;
070: if (length == 0)
071: return 1;
072: int i = 0;
073: for (i = 0; i < startLineIndexes.length - 1; i++) {
074: if (startLineIndexes[i] < position
075: && (startLineIndexes[i + 1] > position))
076: return position - startLineIndexes[i];
077: }
078: int tabCount = 0;
079: int tabSize = 0;
080: if (getCompilationUnit() != null) {
081: tabSize = getCompilationUnit().getFactory()
082: .getEnvironment().getTabulationSize();
083: String source = getCompilationUnit()
084: .getOriginalSourceCode();
085: for (int j = startLineIndexes[i]; j < position; j++) {
086: if (source.charAt(j) == '\t') {
087: tabCount++;
088: }
089: }
090: }
091: return (position - startLineIndexes[i]) - tabCount
092: + (tabCount * tabSize);
093: }
094:
095: int[] lineSeparatorPositions;
096:
097: private int sourceStart, sourceEnd;
098:
099: public SourcePositionImpl(CompilationUnit compilationUnit,
100: int sourceStart, int sourceEnd, int[] lineSeparatorPositions) {
101: super ();
102: this .compilationUnit = compilationUnit;
103: this .sourceStart = sourceStart;
104: this .sourceEnd = sourceEnd;
105: this .lineSeparatorPositions = lineSeparatorPositions;
106: }
107:
108: @Override
109: public Object clone() throws CloneNotSupportedException {
110: return super .clone();
111: }
112:
113: public int getColumn() {
114: return searchColumnNumber(lineSeparatorPositions, sourceStart);
115: }
116:
117: public int getEndColumn() {
118: return searchColumnNumber(lineSeparatorPositions, sourceEnd);
119: }
120:
121: public File getFile() {
122: if (compilationUnit == null)
123: return null;
124: return compilationUnit.getFile();
125: }
126:
127: public int getLine() {
128: return searchLineNumber(lineSeparatorPositions, sourceStart);
129: }
130:
131: public int getEndLine() {
132: return searchLineNumber(lineSeparatorPositions, sourceEnd);
133: }
134:
135: public int getSourceEnd() {
136: return sourceEnd;
137: }
138:
139: public int getSourceStart() {
140: return sourceStart;
141: }
142:
143: /**
144: * Returns a string representation of this position in the form
145: * "sourcefile:line", or "sourcefile" if no line number is available.
146: */
147: public String toString() {
148: int ln = getLine();
149: return (ln >= 1) ? getFile().getAbsolutePath() + ":" + ln
150: : getFile().getAbsolutePath();
151: }
152:
153: @Override
154: public boolean equals(Object obj) {
155: if (!(obj instanceof SourcePosition))
156: return false;
157: SourcePosition s = (SourcePosition) obj;
158: return (getFile() == null ? s.getFile() == null : getFile()
159: .equals(s.getFile()))
160: && getLine() == s.getLine()
161: && getColumn() == s.getColumn();
162: }
163:
164: CompilationUnit compilationUnit;
165:
166: public CompilationUnit getCompilationUnit() {
167: return compilationUnit;
168: }
169:
170: public void setCompilationUnit(CompilationUnit compilationUnit) {
171: this.compilationUnit = compilationUnit;
172: }
173:
174: }
|