PageRenderTime 58ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/java.source/src/org/netbeans/modules/java/source/parsing/CompilationInfoImpl.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 697 lines | 464 code | 86 blank | 147 comment | 81 complexity | 5e0e2e6a259a49507c4ed89fc83bf8b0 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * If you wish your version of this file to be governed by only the CDDL
  28. * or only the GPL Version 2, indicate your decision by adding
  29. * "[Contributor] elects to include this software in this distribution
  30. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  31. * single choice of license, a recipient has the option to distribute
  32. * your version of this file under either the CDDL, the GPL Version 2 or
  33. * to extend the choice of license to its licensees as provided above.
  34. * However, if you add GPL Version 2 code and therefore, elected the GPL
  35. * Version 2 license, then the option applies only if the new code is
  36. * made subject to such option by the copyright holder.
  37. *
  38. * Contributor(s):
  39. *
  40. * Portions Copyrighted 2007 Sun Microsystems, Inc.
  41. */
  42. package org.netbeans.modules.java.source.parsing;
  43. import com.sun.source.tree.CompilationUnitTree;
  44. import com.sun.source.tree.MethodTree;
  45. import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
  46. import com.sun.tools.javac.api.DiagnosticFormatter;
  47. import com.sun.tools.javac.api.JavacTaskImpl;
  48. import com.sun.tools.javac.util.JCDiagnostic;
  49. import com.sun.tools.javac.util.Log;
  50. import java.io.IOException;
  51. import java.util.ArrayList;
  52. import java.util.Arrays;
  53. import java.util.Collection;
  54. import java.util.EnumMap;
  55. import java.util.HashMap;
  56. import java.util.Iterator;
  57. import java.util.List;
  58. import java.util.Locale;
  59. import java.util.Map;
  60. import java.util.Map.Entry;
  61. import java.util.TreeMap;
  62. import java.util.logging.Level;
  63. import java.util.logging.Logger;
  64. import javax.swing.text.Document;
  65. import javax.tools.Diagnostic;
  66. import javax.tools.Diagnostic.Kind;
  67. import javax.tools.DiagnosticListener;
  68. import javax.tools.JavaFileObject;
  69. import org.netbeans.api.java.source.ClasspathInfo;
  70. import org.netbeans.api.java.source.CompilationInfo;
  71. import org.netbeans.api.java.source.CompilationInfo.CacheClearPolicy;
  72. import org.netbeans.api.java.source.JavaSource;
  73. import org.netbeans.api.lexer.TokenHierarchy;
  74. import org.netbeans.modules.java.source.JavaFileFilterQuery;
  75. import org.netbeans.modules.java.source.usages.Pair;
  76. import org.netbeans.modules.parsing.api.Snapshot;
  77. import org.openide.cookies.EditorCookie;
  78. import org.openide.filesystems.FileObject;
  79. import org.openide.loaders.DataObject;
  80. import org.openide.loaders.DataObjectNotFoundException;
  81. import org.openide.util.Exceptions;
  82. /**
  83. *
  84. * @author Tomas Zezula
  85. */
  86. public final class CompilationInfoImpl {
  87. private JavaSource.Phase phase = JavaSource.Phase.MODIFIED;
  88. private CompilationUnitTree compilationUnit;
  89. private JavacTaskImpl javacTask;
  90. private DiagnosticListener<JavaFileObject> diagnosticListener;
  91. private final ClasspathInfo cpInfo;
  92. private Pair<DocPositionRegion,MethodTree> changedMethod;
  93. private final FileObject file;
  94. private final FileObject root;
  95. final JavaFileObject jfo;
  96. //@NotThreadSafe //accessed under parser lock
  97. private Snapshot snapshot;
  98. private final JavacParser parser;
  99. private final boolean isClassFile;
  100. private final boolean isDetached;
  101. JavaSource.Phase parserCrashed = JavaSource.Phase.UP_TO_DATE; //When javac throws an error, the moveToPhase sets this to the last safe phase
  102. private final Map<CacheClearPolicy, Map<Object, Object>> userCache = new EnumMap<CacheClearPolicy, Map<Object, Object>>(CacheClearPolicy.class);
  103. /**
  104. * Creates a new CompilationInfoImpl for given source file
  105. * @param parser used to parse the file
  106. * @param file to be parsed
  107. * @param root the owner of the parsed file
  108. * @param javacTask used javac or null if new one should be created
  109. * @param snapshot rendered content of the file
  110. * @param detached true if the CompilationInfoImpl is detached from parsing infrastructure.
  111. * @throws java.io.IOException
  112. */
  113. CompilationInfoImpl (final JavacParser parser,
  114. final FileObject file,
  115. final FileObject root,
  116. final JavacTaskImpl javacTask,
  117. final DiagnosticListener<JavaFileObject> diagnosticListener,
  118. final Snapshot snapshot,
  119. final boolean detached) throws IOException {
  120. assert parser != null;
  121. this.parser = parser;
  122. this.cpInfo = parser.getClasspathInfo();
  123. assert cpInfo != null;
  124. this.file = file;
  125. this.root = root;
  126. this.snapshot = snapshot;
  127. assert file == null || snapshot != null;
  128. this.jfo = file != null ? JavacParser.jfoProvider.createJavaFileObject(file, root, JavaFileFilterQuery.getFilter(file), snapshot.getText()) : null;
  129. this.javacTask = javacTask;
  130. this.diagnosticListener = diagnosticListener;
  131. this.isClassFile = false;
  132. this.isDetached = detached;
  133. }
  134. /**
  135. * Creates a new CompilationInfoImpl for classpaths
  136. * @param cpInfo classpaths
  137. */
  138. CompilationInfoImpl (final ClasspathInfo cpInfo) {
  139. assert cpInfo != null;
  140. this.parser = null;
  141. this.file = null;
  142. this.root = null;
  143. this.jfo = null;
  144. this.snapshot = null;
  145. this.cpInfo = cpInfo;
  146. this.isClassFile = false;
  147. this.isDetached = false;
  148. }
  149. /**
  150. * Creates a new CompilationInfoImpl for a class file
  151. * @param cpInfo classpaths
  152. * @param file to be analyzed
  153. * @param root the owner of analyzed file
  154. */
  155. CompilationInfoImpl (final ClasspathInfo cpInfo,
  156. final FileObject file,
  157. final FileObject root) throws IOException {
  158. assert cpInfo != null;
  159. assert file != null;
  160. assert root != null;
  161. this.parser = null;
  162. this.file = file;
  163. this.root = root;
  164. this.jfo = FileObjects.nbFileObject(file, root);
  165. this.snapshot = null;
  166. this.cpInfo = cpInfo;
  167. this.isClassFile = true;
  168. this.isDetached = false;
  169. }
  170. void update (final Snapshot snapshot) throws IOException {
  171. assert snapshot != null;
  172. JavacParser.jfoProvider.update(this.jfo, snapshot.getText());
  173. this.snapshot = snapshot;
  174. }
  175. public Snapshot getSnapshot () {
  176. return this.snapshot;
  177. }
  178. /**
  179. * Returns the current phase of the {@link JavaSource}.
  180. * @return {@link JavaSource.Phase} the state which was reached by the {@link JavaSource}.
  181. */
  182. public JavaSource.Phase getPhase() {
  183. return this.phase;
  184. }
  185. public Pair<DocPositionRegion,MethodTree> getChangedTree () {
  186. return this.changedMethod;
  187. }
  188. /**
  189. * Returns the javac tree representing the source file.
  190. * @return {@link CompilationUnitTree} the compilation unit cantaining the top level classes contained in the,
  191. * java source file.
  192. * @throws java.lang.IllegalStateException when the phase is less than {@link JavaSource.Phase#PARSED}
  193. */
  194. public CompilationUnitTree getCompilationUnit() {
  195. if (this.jfo == null) {
  196. throw new IllegalStateException ();
  197. }
  198. if (this.phase.compareTo (JavaSource.Phase.PARSED) < 0)
  199. throw new IllegalStateException("Cannot call getCompilationInfo() if current phase < JavaSource.Phase.PARSED. You must call toPhase(Phase.PARSED) first.");//NOI18N
  200. return this.compilationUnit;
  201. }
  202. /**
  203. * Returns the content of the file represented by the {@link JavaSource}.
  204. * @return String the java source
  205. */
  206. public String getText() {
  207. if (!hasSource()) {
  208. throw new IllegalStateException ();
  209. }
  210. try {
  211. return this.jfo.getCharContent(false).toString();
  212. } catch (IOException ioe) {
  213. //Should never happen
  214. Exceptions.printStackTrace(ioe);
  215. return null;
  216. }
  217. }
  218. /**
  219. * Returns the {@link TokenHierarchy} for the file represented by the {@link JavaSource}.
  220. * @return lexer TokenHierarchy
  221. */
  222. public TokenHierarchy<?> getTokenHierarchy() {
  223. if (!hasSource()) {
  224. throw new IllegalStateException ();
  225. }
  226. try {
  227. return ((SourceFileObject) this.jfo).getTokenHierarchy();
  228. } catch (IOException ioe) {
  229. //Should never happen
  230. Exceptions.printStackTrace(ioe);
  231. return null;
  232. }
  233. }
  234. /**
  235. * Returns the errors in the file represented by the {@link JavaSource}.
  236. * @return an list of {@link Diagnostic}
  237. */
  238. public List<Diagnostic> getDiagnostics() {
  239. if (this.jfo == null) {
  240. throw new IllegalStateException ();
  241. }
  242. Collection<Collection<Diagnostic<? extends JavaFileObject>>> errors = ((DiagnosticListenerImpl)diagnosticListener).getErrors(jfo).values();
  243. List<Diagnostic<? extends JavaFileObject>> partialReparseErrors = ((DiagnosticListenerImpl)diagnosticListener).partialReparseErrors;
  244. List<Diagnostic<? extends JavaFileObject>> affectedErrors = ((DiagnosticListenerImpl)diagnosticListener).affectedErrors;
  245. int errorsSize = 0;
  246. for (Collection<Diagnostic<? extends JavaFileObject>> err : errors) {
  247. errorsSize += err.size();
  248. }
  249. List<Diagnostic> localErrors = new ArrayList<Diagnostic>(errorsSize +
  250. (partialReparseErrors == null ? 0 : partialReparseErrors.size()) +
  251. (affectedErrors == null ? 0 : affectedErrors.size()));
  252. DiagnosticFormatter<JCDiagnostic> formatter = Log.instance(javacTask.getContext()).getDiagnosticFormatter();
  253. for (Collection<Diagnostic<? extends JavaFileObject>> err : errors) {
  254. for (Diagnostic<? extends JavaFileObject> d : err) {
  255. localErrors.add(RichDiagnostic.wrap(d, formatter));
  256. }
  257. }
  258. if (partialReparseErrors != null) {
  259. for (Diagnostic<? extends JavaFileObject> d : partialReparseErrors) {
  260. localErrors.add(RichDiagnostic.wrap(d, formatter));
  261. }
  262. }
  263. if (affectedErrors != null) {
  264. for (Diagnostic<? extends JavaFileObject> d : affectedErrors) {
  265. localErrors.add(RichDiagnostic.wrap(d, formatter));
  266. }
  267. }
  268. return localErrors;
  269. }
  270. /**
  271. * Returns {@link ClasspathInfo} for which this {@link CompilationInfoImpl} was created.
  272. * @return ClasspathInfo
  273. */
  274. public ClasspathInfo getClasspathInfo() {
  275. return this.cpInfo;
  276. }
  277. /**
  278. * Returns {@link JavacParser} which created this {@link CompilationInfoImpl}
  279. * or null when the {@link CompilationInfoImpl} was created for no files.
  280. * @return {@link JavacParser} or null
  281. */
  282. public JavacParser getParser () {
  283. return this.parser;
  284. }
  285. /**
  286. * Returns the {@link FileObject} represented by this {@link CompilationInfo}.
  287. * @return FileObject
  288. */
  289. public FileObject getFileObject () {
  290. return this.file;
  291. }
  292. public FileObject getRoot () {
  293. return this.root;
  294. }
  295. public boolean isClassFile () {
  296. return this.isClassFile;
  297. }
  298. /**
  299. * Returns {@link Document} of this {@link CompilationInfoImpl}
  300. * @return Document or null when the {@link DataObject} doesn't
  301. * exist or has no {@link EditorCookie}.
  302. * @throws java.io.IOException
  303. */
  304. public Document getDocument() {
  305. if (this.file == null) {
  306. return null;
  307. }
  308. if (!this.file.isValid()) {
  309. return null;
  310. }
  311. try {
  312. DataObject od = DataObject.find(file);
  313. EditorCookie ec = od.getCookie(EditorCookie.class);
  314. if (ec != null) {
  315. return ec.getDocument();
  316. } else {
  317. return null;
  318. }
  319. } catch (DataObjectNotFoundException e) {
  320. //may happen when the underlying FileObject has just been deleted
  321. //should be safe to ignore
  322. Logger.getLogger(CompilationInfoImpl.class.getName()).log(Level.FINE, null, e);
  323. return null;
  324. }
  325. }
  326. /**
  327. * Moves the state to required phase. If given state was already reached
  328. * the state is not changed. The method will throw exception if a state is
  329. * illegal required. Acceptable parameters for thid method are <BR>
  330. * <LI>{@link org.netbeans.api.java.source.JavaSource.Phase.PARSED}
  331. * <LI>{@link org.netbeans.api.java.source.JavaSource.Phase.ELEMENTS_RESOLVED}
  332. * <LI>{@link org.netbeans.api.java.source.JavaSource.Phase.RESOLVED}
  333. * <LI>{@link org.netbeans.api.java.source.JavaSource.Phase.UP_TO_DATE}
  334. * @param phase The required phase
  335. * @return the reached state
  336. * @throws IllegalArgumentException in case that given state can not be
  337. * reached using this method
  338. * @throws IOException when the file cannot be red
  339. */
  340. public JavaSource.Phase toPhase(JavaSource.Phase phase ) throws IOException {
  341. if (phase == JavaSource.Phase.MODIFIED) {
  342. throw new IllegalArgumentException( "Invalid phase: " + phase ); //NOI18N
  343. }
  344. if (!hasSource()) {
  345. JavaSource.Phase currentPhase = getPhase();
  346. if (currentPhase.compareTo(phase)<0) {
  347. setPhase(phase);
  348. if (currentPhase == JavaSource.Phase.MODIFIED)
  349. getJavacTask().parse(); // Ensure proper javac initialization
  350. currentPhase = phase;
  351. }
  352. return currentPhase;
  353. }
  354. else {
  355. JavaSource.Phase currentPhase = parser.moveToPhase(phase, this, false);
  356. return currentPhase.compareTo (phase) < 0 ? currentPhase : phase;
  357. }
  358. }
  359. /**
  360. * Returns {@link JavacTaskImpl}, when it doesn't exist
  361. * it's created.
  362. * @return JavacTaskImpl
  363. */
  364. public synchronized JavacTaskImpl getJavacTask() {
  365. if (javacTask == null) {
  366. diagnosticListener = new DiagnosticListenerImpl(this.jfo);
  367. javacTask = JavacParser.createJavacTask(this.file, this.root, this.cpInfo,
  368. this.parser, diagnosticListener, null, isDetached);
  369. }
  370. return javacTask;
  371. }
  372. public Object getCachedValue(Object key) {
  373. for (Map<Object, Object> c : userCache.values()) {
  374. Object res = c.get(key);
  375. if (res != null) return res;
  376. }
  377. return null;
  378. }
  379. public void putCachedValue(Object key, Object value, CacheClearPolicy clearPolicy) {
  380. for (Map<Object, Object> c : userCache.values()) {
  381. c.remove(key);
  382. }
  383. Map<Object, Object> c = userCache.get(clearPolicy);
  384. if (c == null) {
  385. userCache.put(clearPolicy, c = new HashMap<Object, Object>());
  386. }
  387. c.put(key, value);
  388. }
  389. public void taskFinished() {
  390. userCache.remove(CacheClearPolicy.ON_TASK_END);
  391. }
  392. public void dispose() {
  393. userCache.clear();
  394. }
  395. /**
  396. * Returns current {@link DiagnosticListener}
  397. * @return listener
  398. */
  399. DiagnosticListener<JavaFileObject> getDiagnosticListener() {
  400. return diagnosticListener;
  401. }
  402. /**
  403. * Sets the current {@link JavaSource.Phase}
  404. * @param phase
  405. */
  406. void setPhase(final JavaSource.Phase phase) {
  407. assert phase != null;
  408. this.phase = phase;
  409. }
  410. /**
  411. * Sets changed method
  412. * @param changedMethod
  413. */
  414. void setChangedMethod (final Pair<DocPositionRegion,MethodTree> changedMethod) {
  415. this.changedMethod = changedMethod;
  416. userCache.remove(CacheClearPolicy.ON_TASK_END);
  417. userCache.remove(CacheClearPolicy.ON_CHANGE);
  418. }
  419. /**
  420. * Sets the {@link CompilationUnitTree}
  421. * @param compilationUnit
  422. */
  423. void setCompilationUnit(final CompilationUnitTree compilationUnit) {
  424. assert compilationUnit != null;
  425. this.compilationUnit = compilationUnit;
  426. }
  427. private boolean hasSource () {
  428. return this.jfo != null && !isClassFile;
  429. }
  430. // Innerclasses ------------------------------------------------------------
  431. @Trusted
  432. static class DiagnosticListenerImpl implements DiagnosticListener<JavaFileObject> {
  433. private final Map<JavaFileObject, TreeMap<Integer, Collection<Diagnostic<? extends JavaFileObject>>>> source2Errors;
  434. private final JavaFileObject jfo;
  435. private volatile List<Diagnostic<? extends JavaFileObject>> partialReparseErrors;
  436. private volatile List<Diagnostic<? extends JavaFileObject>> affectedErrors;
  437. private volatile int currentDelta;
  438. public DiagnosticListenerImpl(final JavaFileObject jfo) {
  439. this.jfo = jfo;
  440. this.source2Errors = new HashMap<JavaFileObject, TreeMap<Integer, Collection<Diagnostic<? extends JavaFileObject>>>>();
  441. }
  442. @Override
  443. public void report(Diagnostic<? extends JavaFileObject> message) {
  444. if (partialReparseErrors != null) {
  445. if (this.jfo != null && this.jfo == message.getSource()) {
  446. partialReparseErrors.add(message);
  447. }
  448. } else {
  449. TreeMap<Integer, Collection<Diagnostic<? extends JavaFileObject>>> errors = getErrors(message.getSource());
  450. Collection<Diagnostic<? extends JavaFileObject>> diags = errors.get((int) message.getPosition());
  451. if (diags == null) {
  452. errors.put((int) message.getPosition(), diags = new ArrayList<Diagnostic<? extends JavaFileObject>>());
  453. }
  454. diags.add(message);
  455. }
  456. }
  457. private TreeMap<Integer, Collection<Diagnostic<? extends JavaFileObject>>> getErrors(JavaFileObject file) {
  458. TreeMap<Integer, Collection<Diagnostic<? extends JavaFileObject>>> errors = source2Errors.get(file);
  459. if (errors == null) {
  460. source2Errors.put(file, errors = new TreeMap<Integer, Collection<Diagnostic<? extends JavaFileObject>>>());
  461. }
  462. return errors;
  463. }
  464. final boolean hasPartialReparseErrors () {
  465. return this.partialReparseErrors != null && !this.partialReparseErrors.isEmpty();
  466. }
  467. final void startPartialReparse (int from, int to) {
  468. if (partialReparseErrors == null) {
  469. partialReparseErrors = new ArrayList<Diagnostic<? extends JavaFileObject>>();
  470. TreeMap<Integer, Collection<Diagnostic<? extends JavaFileObject>>> errors = getErrors(jfo);
  471. errors.subMap(from, to).clear(); //Remove errors in changed method durring the partial reparse
  472. Map<Integer, Collection<Diagnostic<? extends JavaFileObject>>> tail = errors.tailMap(to);
  473. this.affectedErrors = new ArrayList<Diagnostic<? extends JavaFileObject>>(tail.size());
  474. for (Iterator<Entry<Integer,Collection<Diagnostic<? extends JavaFileObject>>>> it = tail.entrySet().iterator(); it.hasNext();) {
  475. Entry<Integer, Collection<Diagnostic<? extends JavaFileObject>>> e = it.next();
  476. for (Diagnostic<? extends JavaFileObject> d : e.getValue()) {
  477. final JCDiagnostic diagnostic = (JCDiagnostic) d;
  478. if (diagnostic == null) {
  479. throw new IllegalStateException("#184910: diagnostic == null " + mapArraysToLists(Thread.getAllStackTraces())); //NOI18N
  480. }
  481. this.affectedErrors.add(new D (diagnostic));
  482. }
  483. it.remove();
  484. }
  485. }
  486. else {
  487. this.partialReparseErrors.clear();
  488. }
  489. }
  490. final void endPartialReparse (final int delta) {
  491. this.currentDelta+=delta;
  492. }
  493. private static <A,B> Map<A,List<B>> mapArraysToLists (final Map<? extends A, B[]> map) {
  494. final Map<A,List<B>> result = new HashMap<A, List<B>>();
  495. for (Map.Entry<? extends A,B[]> entry : map.entrySet()) {
  496. result.put(entry.getKey(), Arrays.asList(entry.getValue()));
  497. }
  498. return result;
  499. }
  500. private final class D implements Diagnostic {
  501. private final JCDiagnostic delegate;
  502. public D (final JCDiagnostic delegate) {
  503. assert delegate != null;
  504. this.delegate = delegate;
  505. }
  506. @Override
  507. public Kind getKind() {
  508. return this.delegate.getKind();
  509. }
  510. @Override
  511. public Object getSource() {
  512. return this.delegate.getSource();
  513. }
  514. @Override
  515. public long getPosition() {
  516. long ret = this.delegate.getPosition();
  517. if (delegate.hasFixedPositions()) {
  518. ret+=currentDelta;
  519. }
  520. return ret;
  521. }
  522. @Override
  523. public long getStartPosition() {
  524. long ret = this.delegate.getStartPosition();
  525. if (delegate.hasFixedPositions()) {
  526. ret+=currentDelta;
  527. }
  528. return ret;
  529. }
  530. @Override
  531. public long getEndPosition() {
  532. long ret = this.delegate.getEndPosition();
  533. if (delegate.hasFixedPositions()) {
  534. ret+=currentDelta;
  535. }
  536. return ret;
  537. }
  538. @Override
  539. public long getLineNumber() {
  540. return -1;
  541. }
  542. @Override
  543. public long getColumnNumber() {
  544. return -1;
  545. }
  546. @Override
  547. public String getCode() {
  548. return this.delegate.getCode();
  549. }
  550. @Override
  551. public String getMessage(Locale locale) {
  552. return this.delegate.getMessage(locale);
  553. }
  554. }
  555. }
  556. private static final class RichDiagnostic implements Diagnostic {
  557. private final JCDiagnostic delegate;
  558. private final DiagnosticFormatter<JCDiagnostic> formatter;
  559. public RichDiagnostic(JCDiagnostic delegate, DiagnosticFormatter<JCDiagnostic> formatter) {
  560. this.delegate = delegate;
  561. this.formatter = formatter;
  562. }
  563. @Override
  564. public Kind getKind() {
  565. return delegate.getKind();
  566. }
  567. @Override
  568. public Object getSource() {
  569. return delegate.getSource();
  570. }
  571. @Override
  572. public long getPosition() {
  573. return delegate.getPosition();
  574. }
  575. @Override
  576. public long getStartPosition() {
  577. return delegate.getStartPosition();
  578. }
  579. @Override
  580. public long getEndPosition() {
  581. return delegate.getEndPosition();
  582. }
  583. @Override
  584. public long getLineNumber() {
  585. return delegate.getLineNumber();
  586. }
  587. @Override
  588. public long getColumnNumber() {
  589. return delegate.getColumnNumber();
  590. }
  591. @Override
  592. public String getCode() {
  593. return delegate.getCode();
  594. }
  595. @Override
  596. public String getMessage(Locale locale) {
  597. return formatter.format(delegate, locale);
  598. }
  599. @Override
  600. public String toString() {
  601. return delegate.toString();
  602. }
  603. public static Diagnostic wrap(Diagnostic d, DiagnosticFormatter<JCDiagnostic> df) {
  604. if (d instanceof JCDiagnostic) {
  605. return new RichDiagnostic((JCDiagnostic) d, df);
  606. } else {
  607. return d;
  608. }
  609. }
  610. }
  611. }