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 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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. Map<String, Lint.Kind> kinds = new HashMap<String, Lint.Kind>();
  30. /* private */World world;
  31. public final Kind invalidAbsoluteTypeName = new Kind("invalidAbsoluteTypeName", "no match for this type name: {0}");
  32. public final Kind invalidWildcardTypeName = new Kind("invalidWildcardTypeName", "no match for this type pattern: {0}");
  33. public final Kind unresolvableMember = new Kind("unresolvableMember", "can not resolve this member: {0}");
  34. public final Kind typeNotExposedToWeaver = new Kind("typeNotExposedToWeaver",
  35. "this affected type is not exposed to the weaver: {0}");
  36. public final Kind shadowNotInStructure = new Kind("shadowNotInStructure",
  37. "the shadow for this join point is not exposed in the structure model: {0}");
  38. public final Kind unmatchedSuperTypeInCall = new Kind("unmatchedSuperTypeInCall",
  39. "does not match because declaring type is {0}, if match desired use target({1})");
  40. public final Kind unmatchedTargetKind = new Kind("unmatchedTargetKind", "does not match because annotation {0} has @Target{1}");
  41. public final Kind canNotImplementLazyTjp = new Kind("canNotImplementLazyTjp",
  42. "can not implement lazyTjp on this joinpoint {0} because around advice is used");
  43. public final Kind multipleAdviceStoppingLazyTjp = new Kind("multipleAdviceStoppingLazyTjp",
  44. "can not implement lazyTjp at joinpoint {0} because of advice conflicts, see secondary locations to find conflicting advice");
  45. public final Kind needsSerialVersionUIDField = new Kind("needsSerialVersionUIDField",
  46. "serialVersionUID of type {0} needs to be set because of {1}");
  47. public final Kind serialVersionUIDBroken = new Kind("brokeSerialVersionCompatibility",
  48. "serialVersionUID of type {0} is broken because of added field {1}");
  49. public final Kind noInterfaceCtorJoinpoint = new Kind("noInterfaceCtorJoinpoint",
  50. "no interface constructor-execution join point - use {0}+ for implementing classes");
  51. public final Kind noJoinpointsForBridgeMethods = new Kind(
  52. "noJoinpointsForBridgeMethods",
  53. "pointcut did not match on the method call to a bridge method. Bridge methods are generated by the compiler and have no join points");
  54. public final Kind enumAsTargetForDecpIgnored = new Kind("enumAsTargetForDecpIgnored",
  55. "enum type {0} matches a declare parents type pattern but is being ignored");
  56. public final Kind annotationAsTargetForDecpIgnored = new Kind("annotationAsTargetForDecpIgnored",
  57. "annotation type {0} matches a declare parents type pattern but is being ignored");
  58. public final Kind cantMatchArrayTypeOnVarargs = new Kind("cantMatchArrayTypeOnVarargs",
  59. "an array type as the last parameter in a signature does not match on the varargs declared method: {0}");
  60. public final Kind adviceDidNotMatch = new Kind("adviceDidNotMatch", "advice defined in {0} has not been applied");
  61. public final Kind invalidTargetForAnnotation = new Kind("invalidTargetForAnnotation",
  62. "{0} is not a valid target for annotation {1}, this annotation can only be applied to {2}");
  63. public final Kind elementAlreadyAnnotated = new Kind("elementAlreadyAnnotated",
  64. "{0} - already has an annotation of type {1}, cannot add a second instance");
  65. public final Kind runtimeExceptionNotSoftened = new Kind("runtimeExceptionNotSoftened",
  66. "{0} will not be softened as it is already a RuntimeException");
  67. public final Kind uncheckedArgument = new Kind("uncheckedArgument",
  68. "unchecked match of {0} with {1} when argument is an instance of {2} at join point {3}");
  69. public final Kind uncheckedAdviceConversion = new Kind("uncheckedAdviceConversion",
  70. "unchecked conversion when advice applied at shadow {0}, expected {1} but advice uses {2}");
  71. public final Kind noGuardForLazyTjp = new Kind("noGuardForLazyTjp",
  72. "can not build thisJoinPoint lazily for this advice since it has no suitable guard");
  73. public final Kind noExplicitConstructorCall = new Kind("noExplicitConstructorCall",
  74. "inter-type constructor does not contain explicit constructor call: field initializers in the target type will not be executed");
  75. public final Kind aspectExcludedByConfiguration = new Kind("aspectExcludedByConfiguration",
  76. "aspect {0} exluded for class loader {1}");
  77. public final Kind unorderedAdviceAtShadow = new Kind("unorderedAdviceAtShadow",
  78. "at this shadow {0} no precedence is specified between advice applying from aspect {1} and aspect {2}");
  79. public final Kind swallowedExceptionInCatchBlock = new Kind("swallowedExceptionInCatchBlock",
  80. "exception swallowed in catch block");
  81. public final Kind calculatingSerialVersionUID = new Kind("calculatingSerialVersionUID",
  82. "calculated SerialVersionUID for type {0} to be {1}");
  83. public final Kind nonReweavableTypeEncountered = new Kind("nonReweavableTypeEncountered",
  84. "class {0} is already woven and has not been built in reweavable mode");
  85. // there are a lot of messages in the cant find type family - I'm defining an umbrella lint warning that
  86. // allows a user to control their severity (for e.g. ltw or binary weaving)
  87. public final Kind cantFindType = new Kind("cantFindType", "{0}");
  88. public final Kind cantFindTypeAffectingJoinPointMatch = new Kind("cantFindTypeAffectingJPMatch", "{0}");
  89. public final Kind advisingSynchronizedMethods = new Kind("advisingSynchronizedMethods",
  90. "advice matching the synchronized method shadow ''{0}'' will be executed outside the lock rather than inside (compiler limitation)");
  91. public final Kind mustWeaveXmlDefinedAspects = new Kind(
  92. "mustWeaveXmlDefinedAspects",
  93. "XML Defined aspects must be woven in cases where cflow pointcuts are involved. Currently the include/exclude patterns exclude ''{0}''");
  94. public final Kind cannotAdviseJoinpointInInterfaceWithAroundAdvice = new Kind(
  95. "cannotAdviseJoinpointInInterfaceWithAroundAdvice",
  96. "The joinpoint ''{0}'' cannot be advised and is being skipped as the compiler implementation will lead to creation of methods with bodies in an interface (compiler limitation)");
  97. /**
  98. * Indicates an aspect could not be found when attempting reweaving.
  99. */
  100. public final Kind missingAspectForReweaving = new Kind("missingAspectForReweaving",
  101. "aspect {0} cannot be found when reweaving {1}");
  102. private static Trace trace = TraceFactory.getTraceFactory().getTrace(Lint.class);
  103. public Lint(World world) {
  104. if (trace.isTraceEnabled()) {
  105. trace.enter("<init>", this, world);
  106. }
  107. this.world = world;
  108. if (trace.isTraceEnabled()) {
  109. trace.exit("<init>");
  110. }
  111. }
  112. public void setAll(String messageKind) {
  113. if (trace.isTraceEnabled()) {
  114. trace.enter("setAll", this, messageKind);
  115. }
  116. setAll(getMessageKind(messageKind));
  117. if (trace.isTraceEnabled()) {
  118. trace.exit("setAll");
  119. }
  120. }
  121. private void setAll(IMessage.Kind messageKind) {
  122. for (Kind kind : kinds.values()) {
  123. kind.setKind(messageKind);
  124. }
  125. }
  126. public void setFromMap(Map<String,String> lintOptionsMap) {
  127. for (String key: lintOptionsMap.keySet()) {
  128. String value = lintOptionsMap.get(key);
  129. Kind kind = kinds.get(key);
  130. if (kind == null) {
  131. MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_KEY_ERROR, key));
  132. } else {
  133. kind.setKind(getMessageKind(value));
  134. }
  135. }
  136. }
  137. public void setFromProperties(File file) {
  138. if (trace.isTraceEnabled()) {
  139. trace.enter("setFromProperties", this, file);
  140. }
  141. InputStream s = null;
  142. try {
  143. s = new FileInputStream(file);
  144. setFromProperties(s);
  145. } catch (IOException ioe) {
  146. MessageUtil.error(world.getMessageHandler(),
  147. WeaverMessages.format(WeaverMessages.XLINT_LOAD_ERROR, file.getPath(), ioe.getMessage()));
  148. } finally {
  149. if (s != null) {
  150. try {
  151. s.close();
  152. } catch (IOException e) {
  153. // ignore
  154. }
  155. }
  156. }
  157. if (trace.isTraceEnabled()) {
  158. trace.exit("setFromProperties");
  159. }
  160. }
  161. public void loadDefaultProperties() {
  162. InputStream s = getClass().getResourceAsStream("XlintDefault.properties");
  163. if (s == null) {
  164. MessageUtil.warn(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINTDEFAULT_LOAD_ERROR));
  165. return;
  166. }
  167. try {
  168. setFromProperties(s);
  169. } catch (IOException ioe) {
  170. MessageUtil.error(world.getMessageHandler(),
  171. WeaverMessages.format(WeaverMessages.XLINTDEFAULT_LOAD_PROBLEM, ioe.getMessage()));
  172. } finally {
  173. try {
  174. s.close();
  175. } catch (IOException ioe) {
  176. // ignore
  177. }
  178. }
  179. }
  180. private void setFromProperties(InputStream s) throws IOException {
  181. Properties p = new Properties();
  182. p.load(s);
  183. setFromProperties(p);
  184. }
  185. @SuppressWarnings("rawtypes")
  186. public void setFromProperties(Properties properties) {
  187. for (Iterator i = properties.entrySet().iterator(); i.hasNext();) {
  188. Map.Entry entry = (Map.Entry) i.next();
  189. Kind kind = kinds.get(entry.getKey());
  190. if (kind == null) {
  191. MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_KEY_ERROR, entry.getKey()));
  192. } else {
  193. kind.setKind(getMessageKind((String) entry.getValue()));
  194. }
  195. }
  196. }
  197. public Collection<Kind> allKinds() {
  198. return kinds.values();
  199. }
  200. public Kind getLintKind(String name) {
  201. return kinds.get(name);
  202. }
  203. // temporarily suppress the given lint messages
  204. public void suppressKinds(Collection<Kind> lintKind) {
  205. if (lintKind.isEmpty()) {
  206. return;
  207. }
  208. for (Kind k : lintKind) {
  209. k.setSuppressed(true);
  210. }
  211. }
  212. // remove any suppression of lint warnings in place
  213. public void clearAllSuppressions() {
  214. for (Kind k : kinds.values()) {
  215. k.setSuppressed(false);
  216. }
  217. }
  218. public void clearSuppressions(Collection<Lint.Kind> lintKinds) {
  219. for (Kind k : lintKinds) {
  220. k.setSuppressed(false);
  221. }
  222. }
  223. private IMessage.Kind getMessageKind(String v) {
  224. if (v.equals("ignore")) {
  225. return null;
  226. } else if (v.equals("warning")) {
  227. return IMessage.WARNING;
  228. } else if (v.equals("error")) {
  229. return IMessage.ERROR;
  230. }
  231. MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_VALUE_ERROR, v));
  232. return null;
  233. }
  234. public Kind fromKey(String lintkey) {
  235. return kinds.get(lintkey);
  236. }
  237. public class Kind {
  238. private final String name;
  239. private final String message;
  240. private IMessage.Kind kind = IMessage.WARNING;
  241. private boolean isSupressed = false; // by SuppressAjWarnings
  242. public Kind(String name, String message) {
  243. this.name = name;
  244. this.message = message;
  245. kinds.put(this.name, this);
  246. }
  247. public void setSuppressed(boolean shouldBeSuppressed) {
  248. this.isSupressed = shouldBeSuppressed;
  249. }
  250. public boolean isEnabled() {
  251. return (kind != null) && !isSupressed();
  252. }
  253. private boolean isSupressed() {
  254. // can't suppress errors!
  255. return isSupressed && (kind != IMessage.ERROR);
  256. }
  257. public String getName() {
  258. return name;
  259. }
  260. public IMessage.Kind getKind() {
  261. return kind;
  262. }
  263. public void setKind(IMessage.Kind kind) {
  264. this.kind = kind;
  265. }
  266. public void signal(String info, ISourceLocation location) {
  267. if (kind == null) {
  268. return;
  269. }
  270. String text = MessageFormat.format(message, new Object[] { info });
  271. text += " [Xlint:" + name + "]";
  272. world.getMessageHandler().handleMessage(new LintMessage(text, kind, location, null, getLintKind(name)));
  273. }
  274. public void signal(String[] infos, ISourceLocation location, ISourceLocation[] extraLocations) {
  275. if (kind == null) {
  276. return;
  277. }
  278. String text = MessageFormat.format(message, (Object[]) infos);
  279. text += " [Xlint:" + name + "]";
  280. world.getMessageHandler().handleMessage(new LintMessage(text, kind, location, extraLocations, getLintKind(name)));
  281. }
  282. }
  283. }