You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SourceLocation.java 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* *******************************************************************
  2. * Copyright (c) 1999-2001 Xerox Corporation,
  3. * 2002 Palo Alto Research Center, Incorporated (PARC).
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors:
  11. * Xerox/PARC initial implementation
  12. * ******************************************************************/
  13. package org.aspectj.bridge;
  14. import java.io.File;
  15. import org.aspectj.util.LangUtil;
  16. /**
  17. * Immutable source location. This guarantees that the source file is not null and that the numeric values are positive and line ≤
  18. * endLine.
  19. *
  20. * @see org.aspectj.lang.reflect.SourceLocation
  21. * @see org.aspectj.compiler.base.parser.SourceInfo
  22. * @see org.aspectj.tools.ide.SourceLine
  23. * @see org.aspectj.testing.harness.ErrorLine
  24. */
  25. public class SourceLocation implements ISourceLocation {
  26. private static final long serialVersionUID = -5434765814401009794L;
  27. private transient int cachedHashcode = -1;
  28. /** used when SourceLocation is not available */
  29. public static final ISourceLocation UNKNOWN = new SourceLocation(ISourceLocation.NO_FILE, 0, 0, 0);
  30. private final File sourceFile;
  31. private final int startLine;
  32. private final int column;
  33. private final int endLine;
  34. private int offset;
  35. private final String context;
  36. private boolean noColumn;
  37. private String sourceFileName;
  38. /** @throws IllegalArgumentException if the input would not be a valid line */
  39. public static final void validLine(int line) {
  40. if (line < 0) {
  41. throw new IllegalArgumentException("negative line: " + line);
  42. } else if (line > ISourceLocation.MAX_LINE) {
  43. throw new IllegalArgumentException("line too large: " + line);
  44. }
  45. }
  46. /** @throws IllegalArgumentException if the input would not be a valid column */
  47. public static final void validColumn(int column) {
  48. if (column < 0) {
  49. throw new IllegalArgumentException("negative column: " + column);
  50. } else if (column > ISourceLocation.MAX_COLUMN) {
  51. throw new IllegalArgumentException("column too large: " + column);
  52. }
  53. }
  54. /**
  55. * Same as SourceLocation(file, line, line, 0), except that column is not rendered during toString()
  56. */
  57. public SourceLocation(File file, int line) {
  58. this(file, line, line, NO_COLUMN);
  59. }
  60. /** same as SourceLocation(file, line, endLine, ISourceLocation.NO_COLUMN) */
  61. public SourceLocation(File file, int line, int endLine) {
  62. this(file, line, endLine, ISourceLocation.NO_COLUMN);
  63. }
  64. /**
  65. * @param file File of the source; if null, use ISourceLocation.NO_FILE, not null
  66. * @param line int starting line of the location - positive number
  67. * @param endLine int ending line of the location - &le; starting line
  68. * @param column int character position of starting location - positive number
  69. */
  70. public SourceLocation(File file, int line, int endLine, int column) {
  71. this(file, line, endLine, column, (String) null);
  72. }
  73. public SourceLocation(File file, int line, int endLine, int column, String context) {
  74. if (column == NO_COLUMN) {
  75. column = 0;
  76. noColumn = true;
  77. }
  78. if (null == file) {
  79. file = ISourceLocation.NO_FILE;
  80. }
  81. validLine(line);
  82. validLine(endLine);
  83. LangUtil.throwIaxIfFalse(line <= endLine, line + " > " + endLine);
  84. LangUtil.throwIaxIfFalse(column >= 0, "negative column: " + column);
  85. this.sourceFile = file;
  86. this.startLine = line;
  87. this.column = column;
  88. this.endLine = endLine;
  89. this.context = context;
  90. }
  91. public SourceLocation(File file, int line, int endLine, int column, String context, String sourceFileName) {
  92. this(file, line, endLine, column, context);
  93. this.sourceFileName = sourceFileName;
  94. }
  95. public File getSourceFile() {
  96. return sourceFile;
  97. }
  98. public int getLine() {
  99. return startLine;
  100. }
  101. /**
  102. * @return int actual column or 0 if not available per constructor treatment of ISourceLocation.NO_COLUMN
  103. */
  104. public int getColumn() {
  105. return column;
  106. }
  107. public int getEndLine() {
  108. return endLine;
  109. }
  110. /** @return null String or application-specific context */
  111. public String getContext() {
  112. return context;
  113. }
  114. /** @return String {context\n}{file:}line{:column} */
  115. public String toString() {
  116. StringBuffer sb = new StringBuffer();
  117. if (null != context) {
  118. sb.append(context);
  119. sb.append(LangUtil.EOL);
  120. }
  121. if (sourceFile != ISourceLocation.NO_FILE) {
  122. sb.append(sourceFile.getPath());
  123. }
  124. if (startLine > 0) {
  125. sb.append(":");
  126. sb.append(startLine); // "" + startLine + "-" + endLine);
  127. }
  128. if (!noColumn) {
  129. sb.append(":" + column);
  130. }
  131. if (offset >= 0) {
  132. sb.append("::" + offset);
  133. }
  134. return sb.toString();
  135. }
  136. // XXX Ctors for this type should know about an offset, rather than
  137. // it being set through these methods - but there are just too many
  138. // ctors at the moment! It needs sorting out.
  139. public int getOffset() {
  140. return offset;
  141. }
  142. public void setOffset(int i) {
  143. cachedHashcode = -1;
  144. offset = i;
  145. }
  146. public String getSourceFileName() {
  147. return sourceFileName;
  148. }
  149. public boolean equals(Object obj) {
  150. if (!(obj instanceof SourceLocation)) {
  151. return false;
  152. }
  153. SourceLocation o = (SourceLocation) obj;
  154. return startLine == o.startLine && column == o.column && endLine == o.endLine && offset == o.offset
  155. && (sourceFile == null ? o.sourceFile == null : sourceFile.equals(o.sourceFile))
  156. && (context == null ? o.context == null : context.equals(o.context)) && noColumn == o.noColumn
  157. && (sourceFileName == null ? o.sourceFileName == null : sourceFileName.equals(o.sourceFileName));
  158. }
  159. public int hashCode() {
  160. if (cachedHashcode == -1) {
  161. cachedHashcode = (sourceFile == null ? 0 : sourceFile.hashCode());
  162. cachedHashcode = cachedHashcode * 37 + startLine;
  163. cachedHashcode = cachedHashcode * 37 + column;
  164. cachedHashcode = cachedHashcode * 37 + endLine;
  165. cachedHashcode = cachedHashcode * 37 + offset;
  166. cachedHashcode = cachedHashcode * 37 + (context == null ? 0 : context.hashCode());
  167. cachedHashcode = cachedHashcode * 37 + (noColumn ? 0 : 1);
  168. cachedHashcode = cachedHashcode * 37 + (sourceFileName == null ? 0 : sourceFileName.hashCode());
  169. }
  170. return cachedHashcode;
  171. }
  172. }