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.

Lint.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver;
  13. import java.io.File;
  14. import java.io.FileInputStream;
  15. import java.io.IOException;
  16. import java.io.InputStream;
  17. import java.text.MessageFormat;
  18. import java.util.Collection;
  19. import java.util.HashMap;
  20. import java.util.Iterator;
  21. import java.util.Map;
  22. import java.util.Properties;
  23. import org.aspectj.bridge.IMessage;
  24. import org.aspectj.bridge.ISourceLocation;
  25. import org.aspectj.bridge.MessageUtil;
  26. import org.aspectj.weaver.tools.Trace;
  27. import org.aspectj.weaver.tools.TraceFactory;
  28. public class Lint {
  29. /* private */ Map kinds = new HashMap();
  30. /* private */ World world;
  31. public final Kind invalidAbsoluteTypeName =
  32. new Kind("invalidAbsoluteTypeName", "no match for this type name: {0}");
  33. public final Kind invalidWildcardTypeName =
  34. new Kind("invalidWildcardTypeName", "no match for this type pattern: {0}");
  35. public final Kind unresolvableMember =
  36. new Kind("unresolvableMember", "can not resolve this member: {0}");
  37. public final Kind typeNotExposedToWeaver =
  38. new Kind("typeNotExposedToWeaver", "this affected type is not exposed to the weaver: {0}");
  39. public final Kind shadowNotInStructure =
  40. new Kind("shadowNotInStructure", "the shadow for this join point is not exposed in the structure model: {0}");
  41. public final Kind unmatchedSuperTypeInCall =
  42. new Kind("unmatchedSuperTypeInCall", "does not match because declaring type is {0}, if match desired use target({1})");
  43. public final Kind unmatchedTargetKind =
  44. new Kind("unmatchedTargetKind", "does not match because annotation {0} has @Target{1}");
  45. public final Kind canNotImplementLazyTjp =
  46. new Kind("canNotImplementLazyTjp", "can not implement lazyTjp on this joinpoint {0} because around advice is used");
  47. public final Kind multipleAdviceStoppingLazyTjp =
  48. new Kind("multipleAdviceStoppingLazyTjp", "can not implement lazyTjp at joinpoint {0} because of advice conflicts, see secondary locations to find conflicting advice");
  49. public final Kind needsSerialVersionUIDField =
  50. new Kind("needsSerialVersionUIDField", "serialVersionUID of type {0} needs to be set because of {1}");
  51. public final Kind serialVersionUIDBroken =
  52. new Kind("brokeSerialVersionCompatibility", "serialVersionUID of type {0} is broken because of added field {1}");
  53. public final Kind noInterfaceCtorJoinpoint =
  54. new Kind("noInterfaceCtorJoinpoint","no interface constructor-execution join point - use {0}+ for implementing classes");
  55. public final Kind noJoinpointsForBridgeMethods =
  56. new Kind("noJoinpointsForBridgeMethods","pointcut did not match on the method call to a bridge method. Bridge methods are generated by the compiler and have no join points");
  57. public final Kind enumAsTargetForDecpIgnored =
  58. new Kind("enumAsTargetForDecpIgnored","enum type {0} matches a declare parents type pattern but is being ignored");
  59. public final Kind annotationAsTargetForDecpIgnored =
  60. new Kind("annotationAsTargetForDecpIgnored","annotation type {0} matches a declare parents type pattern but is being ignored");
  61. public final Kind cantMatchArrayTypeOnVarargs =
  62. new Kind("cantMatchArrayTypeOnVarargs","an array type as the last parameter in a signature does not match on the varargs declared method: {0}");
  63. public final Kind adviceDidNotMatch =
  64. new Kind("adviceDidNotMatch","advice defined in {0} has not been applied");
  65. public final Kind invalidTargetForAnnotation =
  66. new Kind("invalidTargetForAnnotation","{0} is not a valid target for annotation {1}, this annotation can only be applied to {2}");
  67. public final Kind elementAlreadyAnnotated =
  68. new Kind("elementAlreadyAnnotated","{0} - already has an annotation of type {1}, cannot add a second instance");
  69. public final Kind runtimeExceptionNotSoftened =
  70. new Kind("runtimeExceptionNotSoftened","{0} will not be softened as it is already a RuntimeException");
  71. public final Kind uncheckedArgument =
  72. new Kind("uncheckedArgument","unchecked match of {0} with {1} when argument is an instance of {2} at join point {3}");
  73. public final Kind uncheckedAdviceConversion =
  74. new Kind("uncheckedAdviceConversion","unchecked conversion when advice applied at shadow {0}, expected {1} but advice uses {2}");
  75. public final Kind noGuardForLazyTjp =
  76. new Kind("noGuardForLazyTjp","can not build thisJoinPoint lazily for this advice since it has no suitable guard");
  77. public final Kind noExplicitConstructorCall =
  78. new Kind("noExplicitConstructorCall","inter-type constructor does not contain explicit constructor call: field initializers in the target type will not be executed");
  79. public final Kind aspectExcludedByConfiguration =
  80. new Kind("aspectExcludedByConfiguration","aspect {0} exluded for class loader {1}");
  81. public final Kind unorderedAdviceAtShadow =
  82. new Kind("unorderedAdviceAtShadow","at this shadow {0} no precedence is specified between advice applying from aspect {1} and aspect {2}");
  83. public final Kind swallowedExceptionInCatchBlock =
  84. new Kind("swallowedExceptionInCatchBlock","exception swallowed in catch block");
  85. public final Kind calculatingSerialVersionUID =
  86. new Kind("calculatingSerialVersionUID","calculated SerialVersionUID for type {0} to be {1}");
  87. // there are a lot of messages in the cant find type family - I'm defining an umbrella lint warning that
  88. // allows a user to control their severity (for e.g. ltw or binary weaving)
  89. public final Kind cantFindType =
  90. new Kind("cantFindType","{0}");
  91. public final Kind cantFindTypeAffectingJoinPointMatch = new Kind("cantFindTypeAffectingJPMatch","{0}");
  92. public final Kind advisingSynchronizedMethods = new Kind("advisingSynchronizedMethods",
  93. "advice matching the synchronized method shadow ''{0}'' will be executed outside the lock rather than inside (compiler limitation)");
  94. public final Kind mustWeaveXmlDefinedAspects = new Kind("mustWeaveXmlDefinedAspects",
  95. "XML Defined aspects must be woven in cases where cflow pointcuts are involved. Currently the include/exclude patterns exclude ''{0}''");
  96. private static Trace trace = TraceFactory.getTraceFactory().getTrace(Lint.class);
  97. public Lint(World world) {
  98. if (trace.isTraceEnabled()) trace.enter("<init>",this,world);
  99. this.world = world;
  100. if (trace.isTraceEnabled()) trace.exit("<init>");
  101. }
  102. public void setAll(String messageKind) {
  103. if (trace.isTraceEnabled()) trace.enter("setAll",this,messageKind);
  104. setAll(getMessageKind(messageKind));
  105. if (trace.isTraceEnabled()) trace.exit("setAll");
  106. }
  107. private void setAll(IMessage.Kind messageKind) {
  108. for (Iterator i = kinds.values().iterator(); i.hasNext(); ) {
  109. Kind kind = (Kind)i.next();
  110. kind.setKind(messageKind);
  111. }
  112. }
  113. public void setFromProperties(File file) {
  114. if (trace.isTraceEnabled()) trace.enter("setFromProperties",this,file);
  115. try {
  116. InputStream s = new FileInputStream(file);
  117. setFromProperties(s);
  118. } catch (IOException ioe) {
  119. MessageUtil.error(world.getMessageHandler(),
  120. WeaverMessages.format(WeaverMessages.XLINT_LOAD_ERROR,file.getPath(),ioe.getMessage()));
  121. }
  122. if (trace.isTraceEnabled()) trace.exit("setFromProperties");
  123. }
  124. public void loadDefaultProperties() {
  125. InputStream s = getClass().getResourceAsStream("XlintDefault.properties");
  126. if (s == null) {
  127. MessageUtil.warn(world.getMessageHandler(),
  128. WeaverMessages.format(WeaverMessages.XLINTDEFAULT_LOAD_ERROR));
  129. return;
  130. }
  131. try {
  132. setFromProperties(s);
  133. } catch (IOException ioe) {
  134. MessageUtil.error(world.getMessageHandler(),
  135. WeaverMessages.format(WeaverMessages.XLINTDEFAULT_LOAD_PROBLEM,ioe.getMessage()));
  136. }
  137. }
  138. private void setFromProperties(InputStream s) throws IOException {
  139. Properties p = new Properties();
  140. p.load(s);
  141. setFromProperties(p);
  142. }
  143. public void setFromProperties(Properties properties) {
  144. for (Iterator i = properties.entrySet().iterator(); i.hasNext(); ) {
  145. Map.Entry entry = (Map.Entry)i.next();
  146. Kind kind = (Kind)kinds.get(entry.getKey());
  147. if (kind == null) {
  148. MessageUtil.error(world.getMessageHandler(),
  149. WeaverMessages.format(WeaverMessages.XLINT_KEY_ERROR,entry.getKey()));
  150. } else {
  151. kind.setKind(getMessageKind((String)entry.getValue()));
  152. }
  153. }
  154. }
  155. public Collection allKinds() {
  156. return kinds.values();
  157. }
  158. public Kind getLintKind(String name) {
  159. return (Kind) kinds.get(name);
  160. }
  161. // temporarily suppress the given lint messages
  162. public void suppressKinds(Collection lintKind) {
  163. if (lintKind.isEmpty()) return;
  164. for (Iterator iter = lintKind.iterator(); iter.hasNext();) {
  165. Kind k = (Kind) iter.next();
  166. k.setSuppressed(true);
  167. }
  168. }
  169. // remove any suppression of lint warnings in place
  170. public void clearAllSuppressions() {
  171. for (Iterator iter = kinds.values().iterator(); iter.hasNext();) {
  172. Kind k = (Kind) iter.next();
  173. k.setSuppressed(false);
  174. }
  175. }
  176. public void clearSuppressions(Collection lintKind) {
  177. if (lintKind.isEmpty()) return;
  178. for (Iterator iter = lintKind.iterator(); iter.hasNext();) {
  179. Kind k = (Kind) iter.next();
  180. k.setSuppressed(false);
  181. }
  182. }
  183. private IMessage.Kind getMessageKind(String v) {
  184. if (v.equals("ignore")) return null;
  185. else if (v.equals("warning")) return IMessage.WARNING;
  186. else if (v.equals("error")) return IMessage.ERROR;
  187. MessageUtil.error(world.getMessageHandler(),
  188. WeaverMessages.format(WeaverMessages.XLINT_VALUE_ERROR,v));
  189. return null;
  190. }
  191. public Kind fromKey(String lintkey) {
  192. return (Lint.Kind)kinds.get(lintkey);
  193. }
  194. public class Kind {
  195. private String name;
  196. private String message;
  197. private IMessage.Kind kind = IMessage.WARNING;
  198. private boolean isSupressed = false; // by SuppressAjWarnings
  199. public Kind(String name, String message) {
  200. this.name = name;
  201. this.message = message;
  202. kinds.put(this.name, this);
  203. }
  204. public void setSuppressed(boolean shouldBeSuppressed) {
  205. this.isSupressed = shouldBeSuppressed;
  206. }
  207. public boolean isEnabled() {
  208. return (kind != null) && !isSupressed();
  209. }
  210. private boolean isSupressed() {
  211. // can't suppress errors!
  212. return isSupressed && (kind != IMessage.ERROR);
  213. }
  214. public String getName() {
  215. return name;
  216. }
  217. public IMessage.Kind getKind() {
  218. return kind;
  219. }
  220. public void setKind(IMessage.Kind kind) {
  221. this.kind = kind;
  222. }
  223. public void signal(String info, ISourceLocation location) {
  224. if (kind == null) return;
  225. String text = MessageFormat.format(message, new Object[] {info} );
  226. text += " [Xlint:" + name + "]";
  227. world.getMessageHandler().handleMessage(
  228. new LintMessage(text, kind, location,null,getLintKind(name)));
  229. }
  230. public void signal(String[] infos, ISourceLocation location, ISourceLocation[] extraLocations) {
  231. if (kind == null) return;
  232. String text = MessageFormat.format(message, (Object[])infos );
  233. text += " [Xlint:" + name + "]";
  234. world.getMessageHandler().handleMessage(
  235. new LintMessage(text, kind, location,extraLocations,getLintKind(name)));
  236. }
  237. }
  238. }