1 /* 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javac.code; 27 28 import java.util.HashMap; 29 import java.util.Map; 30 31 import com.sun.tools.javac.tree.EndPosTable; 32 import com.sun.tools.javac.tree.JCTree; 33 import com.sun.tools.javac.util.Assert; 34 import com.sun.tools.javac.util.Context; 35 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 36 import com.sun.tools.javac.util.ListBuffer; 37 38 /** 39 * 40 * <p><b>This is NOT part of any supported API. 41 * If you write code that depends on this, you do so at your own risk. 42 * This code and its internal interfaces are subject to change or 43 * deletion without notice.</b> 44 */ 45 public class DeferredLintHandler { 46 protected static final Context.Key<DeferredLintHandler> deferredLintHandlerKey = 47 new Context.Key<DeferredLintHandler>(); 48 instance(Context context)49 public static DeferredLintHandler instance(Context context) { 50 DeferredLintHandler instance = context.get(deferredLintHandlerKey); 51 if (instance == null) 52 instance = new DeferredLintHandler(context); 53 return instance; 54 } 55 DeferredLintHandler(Context context)56 protected DeferredLintHandler(Context context) { 57 context.put(deferredLintHandlerKey, this); 58 this.currentPos = IMMEDIATE_POSITION; 59 } 60 61 /**An interface for deferred lint reporting - loggers passed to 62 * {@link #report(LintLogger) } will be called when 63 * {@link #flush(DiagnosticPosition) } is invoked. 64 */ 65 public interface LintLogger { report()66 void report(); 67 } 68 69 private DiagnosticPosition currentPos; 70 private Map<DiagnosticPosition, ListBuffer<LintLogger>> loggersQueue = new HashMap<DiagnosticPosition, ListBuffer<LintLogger>>(); 71 72 /**Associate the given logger with the current position as set by {@link #setPos(DiagnosticPosition) }. 73 * Will be invoked when {@link #flush(DiagnosticPosition) } will be invoked with the same position. 74 * <br> 75 * Will invoke the logger synchronously if {@link #immediate() } was called 76 * instead of {@link #setPos(DiagnosticPosition) }. 77 */ report(LintLogger logger)78 public void report(LintLogger logger) { 79 if (currentPos == IMMEDIATE_POSITION) { 80 logger.report(); 81 } else { 82 ListBuffer<LintLogger> loggers = loggersQueue.get(currentPos); 83 if (loggers == null) { 84 loggersQueue.put(currentPos, loggers = new ListBuffer<>()); 85 } 86 loggers.append(logger); 87 } 88 } 89 90 /**Invoke all {@link LintLogger}s that were associated with the provided {@code pos}. 91 */ flush(DiagnosticPosition pos)92 public void flush(DiagnosticPosition pos) { 93 ListBuffer<LintLogger> loggers = loggersQueue.get(pos); 94 if (loggers != null) { 95 for (LintLogger lintLogger : loggers) { 96 lintLogger.report(); 97 } 98 loggersQueue.remove(pos); 99 } 100 } 101 102 /**Sets the current position to the provided {@code currentPos}. {@link LintLogger}s 103 * passed to subsequent invocations of {@link #report(LintLogger) } will be associated 104 * with the given position. 105 */ setPos(DiagnosticPosition currentPos)106 public DiagnosticPosition setPos(DiagnosticPosition currentPos) { 107 DiagnosticPosition prevPosition = this.currentPos; 108 this.currentPos = currentPos; 109 return prevPosition; 110 } 111 112 /**{@link LintLogger}s passed to subsequent invocations of 113 * {@link #report(LintLogger) } will be invoked immediately. 114 */ immediate()115 public DiagnosticPosition immediate() { 116 return setPos(IMMEDIATE_POSITION); 117 } 118 119 private static final DiagnosticPosition IMMEDIATE_POSITION = new DiagnosticPosition() { 120 @Override 121 public JCTree getTree() { 122 Assert.error(); 123 return null; 124 } 125 126 @Override 127 public int getStartPosition() { 128 Assert.error(); 129 return -1; 130 } 131 132 @Override 133 public int getPreferredPosition() { 134 Assert.error(); 135 return -1; 136 } 137 138 @Override 139 public int getEndPosition(EndPosTable endPosTable) { 140 Assert.error(); 141 return -1; 142 } 143 }; 144 } 145