19a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee/**
29a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * Copyright (C) 2006 Google Inc.
39a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee *
49a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * Licensed under the Apache License, Version 2.0 (the "License");
59a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * you may not use this file except in compliance with the License.
69a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * You may obtain a copy of the License at
79a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee *
89a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * http://www.apache.org/licenses/LICENSE-2.0
99a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee *
109a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * Unless required by applicable law or agreed to in writing, software
119a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * distributed under the License is distributed on an "AS IS" BASIS,
129a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * See the License for the specific language governing permissions and
149a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * limitations under the License.
159a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee */
169a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee
179a227bef3b82a045323ef2cf38ec60b2e42cf0felimpbizkit@gmail.compackage com.google.inject.internal.util;
189a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee
198743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruberimport com.google.common.cache.CacheBuilder;
208743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruberimport com.google.common.cache.CacheLoader;
218743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruberimport com.google.common.cache.LoadingCache;
22b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.MapMaker;
23b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
249119a6353335397a8f5849899900e937dcdc05d3kevinbimport java.io.IOException;
259119a6353335397a8f5849899900e937dcdc05d3kevinbimport java.lang.reflect.Constructor;
269a3861be25ab810338456bcb4f606b6a0115fd95crazybobleeimport java.lang.reflect.Member;
279a3861be25ab810338456bcb4f606b6a0115fd95crazybobleeimport java.util.Map;
289a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee
299a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee/**
309a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * Creates stack trace elements for members.
319a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee *
329a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee * @author crazybob@google.com (Bob Lee)
339a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee */
349a3861be25ab810338456bcb4f606b6a0115fd95crazybobleepublic class StackTraceElements {
359a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee
36ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber  private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
37ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber  private static final InMemoryStackTraceElement[] EMPTY_INMEMORY_STACK_TRACE =
38ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      new InMemoryStackTraceElement[0];
39ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber
404f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit  /*if[AOP]*/
418743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber  static final LoadingCache<Class<?>, LineNumbers> lineNumbersCache =
428743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber      CacheBuilder.newBuilder().weakKeys().softValues().build(
438743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber          new CacheLoader<Class<?>, LineNumbers>() {
448743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber            public LineNumbers load(Class<?> key) {
458743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber              try {
468743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber                return new LineNumbers(key);
478743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber              }
488743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber              catch (IOException e) {
498743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber                throw new RuntimeException(e);
508743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber              }
518743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber            }
528743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber          });
534f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit  /*end[AOP]*/
548743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber
55605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  private static Map<Object, Object> cache = new MapMaker().makeMap();
56605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  private static final String UNKNOWN_SOURCE = "Unknown Source";
578743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber
589a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee  public static Object forMember(Member member) {
599a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee    if (member == null) {
609532e6267f55105992301add5accfb5c62fdeed8limpbizkit      return SourceProvider.UNKNOWN_SOURCE;
619a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee    }
629a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee
639a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee    Class declaringClass = member.getDeclaringClass();
64564053fc876faf8325bb0d11e009c650bfaa588blimpbizkit
654f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    /*if[AOP]*/
668743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber    LineNumbers lineNumbers = lineNumbersCache.getUnchecked(declaringClass);
674f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    String fileName = lineNumbers.getSource();
684f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    Integer lineNumberOrNull = lineNumbers.getLineNumber(member);
694f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    int lineNumber = lineNumberOrNull == null ? lineNumbers.getFirstLine() : lineNumberOrNull;
704f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    /*end[AOP]*/
714f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    /*if[NO_AOP]
724f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    String fileName = null;
734f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    int lineNumber = -1;
744f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    end[NO_AOP]*/
75564053fc876faf8325bb0d11e009c650bfaa588blimpbizkit
76dfee9fd5f78c5f1f769713b603e4e92a0b7b01e3sberlin    Class<? extends Member> memberType = Classes.memberType(member);
77564053fc876faf8325bb0d11e009c650bfaa588blimpbizkit    String memberName = memberType == Constructor.class ? "<init>" : member.getName();
784f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    return new StackTraceElement(declaringClass.getName(), memberName, fileName, lineNumber);
799a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee  }
809a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee
819a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee  public static Object forType(Class<?> implementation) {
824f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    /*if[AOP]*/
838743a0bb0fb49f30117c846880a7df2e7b36657eChristian Edward Gruber    LineNumbers lineNumbers = lineNumbersCache.getUnchecked(implementation);
844f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    int lineNumber = lineNumbers.getFirstLine();
854f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    String fileName = lineNumbers.getSource();
864f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    /*end[AOP]*/
874f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    /*if[NO_AOP]
884f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    String fileName = null;
894f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    int lineNumber = -1;
904f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    end[NO_AOP]*/
914f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit
924f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit    return new StackTraceElement(implementation.getName(), "class", fileName, lineNumber);
939a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee  }
94605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
95605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  /**
96605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber   * Clears the internal cache for {@link StackTraceElement StackTraceElements}.
97605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber   */
98605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  public static void clearCache() {
99605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    cache.clear();
100605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  }
101605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
102605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  /**
103605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber   * Returns encoded in-memory version of {@link StackTraceElement StackTraceElements}.
104605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber   */
105605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  public static InMemoryStackTraceElement[] convertToInMemoryStackTraceElement(
106605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      StackTraceElement[] stackTraceElements) {
107ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber    if (stackTraceElements.length == 0) {
108ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      return EMPTY_INMEMORY_STACK_TRACE;
109ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber    }
110605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    InMemoryStackTraceElement[] inMemoryStackTraceElements =
111605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        new InMemoryStackTraceElement[stackTraceElements.length];
112605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    for (int i = 0; i < stackTraceElements.length; i++) {
113605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      inMemoryStackTraceElements[i] =
114605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber          weakIntern(new InMemoryStackTraceElement(stackTraceElements[i]));
115605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
116605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    return inMemoryStackTraceElements;
117605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  }
118605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
119605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  /**
120605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber   * Decodes in-memory stack trace elements to regular {@link StackTraceElement StackTraceElements}.
121605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber   */
122605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  public static StackTraceElement[] convertToStackTraceElement(
123605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      InMemoryStackTraceElement[] inMemoryStackTraceElements) {
124ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber    if (inMemoryStackTraceElements.length == 0) {
125ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      return EMPTY_STACK_TRACE;
126ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber    }
127605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    StackTraceElement[] stackTraceElements =
128605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        new StackTraceElement[inMemoryStackTraceElements.length];
129605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    for (int i = 0; i < inMemoryStackTraceElements.length; i++) {
130605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      String declaringClass = inMemoryStackTraceElements[i].getClassName();
131605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      String methodName = inMemoryStackTraceElements[i].getMethodName();
132605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      int lineNumber = inMemoryStackTraceElements[i].getLineNumber();
133605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      stackTraceElements[i] =
134605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber          new StackTraceElement(declaringClass, methodName, UNKNOWN_SOURCE, lineNumber);
135605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
136605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    return stackTraceElements;
137605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  }
138605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
139605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  private static InMemoryStackTraceElement weakIntern(
140605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      InMemoryStackTraceElement inMemoryStackTraceElement) {
141605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    InMemoryStackTraceElement cached =
142605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        (InMemoryStackTraceElement) cache.get(inMemoryStackTraceElement);
143605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    if (cached != null) {
144605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return cached;
145605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
146605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    inMemoryStackTraceElement = new InMemoryStackTraceElement(
147605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        weakIntern(inMemoryStackTraceElement.getClassName()),
148605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        weakIntern(inMemoryStackTraceElement.getMethodName()),
149605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        inMemoryStackTraceElement.getLineNumber());
150605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    cache.put(inMemoryStackTraceElement, inMemoryStackTraceElement);
151605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    return inMemoryStackTraceElement;
152605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  }
153605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
154605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  private static String weakIntern(String s) {
155605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    String cached = (String) cache.get(s);
156605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    if (cached != null) {
157605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return cached;
158605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
159605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    cache.put(s, s);
160605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    return s;
161605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  }
162605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
163605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  /**
164605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber   * In-Memory version of {@link StackTraceElement} that does not store the file name.
165605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber   */
166605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  public static class InMemoryStackTraceElement {
167605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    private String declaringClass;
168605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    private String methodName;
169605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    private int lineNumber;
170605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
171605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    InMemoryStackTraceElement(StackTraceElement ste) {
172605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      this(ste.getClassName(), ste.getMethodName(), ste.getLineNumber());
173605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
174605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
175605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    InMemoryStackTraceElement(String declaringClass, String methodName, int lineNumber) {
176605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      this.declaringClass = declaringClass;
177605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      this.methodName = methodName;
178605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      this.lineNumber = lineNumber;
179605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
180605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
181605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    String getClassName() {
182605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return declaringClass;
183605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
184605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
185605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    String getMethodName() {
186605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return methodName;
187605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
188605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
189605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    int getLineNumber() {
190605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return lineNumber;
191605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
192605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
193605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    @Override
194605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    public boolean equals(Object obj) {
195605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      if (obj == this) {
196605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        return true;
197605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      }
198605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      if (!(obj instanceof InMemoryStackTraceElement)) {
199605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        return false;
200605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      }
201605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      InMemoryStackTraceElement e = (InMemoryStackTraceElement) obj;
202605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return e.declaringClass.equals(declaringClass) && e.lineNumber == lineNumber &&
203605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber          methodName.equals(e.methodName);
204605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
205605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
206605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    @Override
207605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    public int hashCode() {
208605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      int result = 31 * declaringClass.hashCode() + methodName.hashCode();
209605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      result = 31 * result + lineNumber;
210605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return result;
211605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
212605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
213605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    @Override
214605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    public String toString() {
215605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return declaringClass + "." + methodName + "(" + lineNumber + ")";
216605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
217605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber  }
2189a3861be25ab810338456bcb4f606b6a0115fd95crazyboblee}
219