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 = new Context.Key<>(); 47 instance(Context context)48 public static DeferredLintHandler instance(Context context) { 49 DeferredLintHandler instance = context.get(deferredLintHandlerKey); 50 if (instance == null) 51 instance = new DeferredLintHandler(context); 52 return instance; 53 } 54 DeferredLintHandler(Context context)55 protected DeferredLintHandler(Context context) { 56 context.put(deferredLintHandlerKey, this); 57 this.currentPos = IMMEDIATE_POSITION; 58 } 59 60 /**An interface for deferred lint reporting - loggers passed to 61 * {@link #report(LintLogger) } will be called when 62 * {@link #flush(DiagnosticPosition) } is invoked. 63 */ 64 public interface LintLogger { report()65 void report(); 66 } 67 68 private DiagnosticPosition currentPos; 69 private Map<DiagnosticPosition, ListBuffer<LintLogger>> loggersQueue = new HashMap<>(); 70 71 /**Associate the given logger with the current position as set by {@link #setPos(DiagnosticPosition) }. 72 * Will be invoked when {@link #flush(DiagnosticPosition) } will be invoked with the same position. 73 * <br> 74 * Will invoke the logger synchronously if {@link #immediate() } was called 75 * instead of {@link #setPos(DiagnosticPosition) }. 76 */ report(LintLogger logger)77 public void report(LintLogger logger) { 78 if (currentPos == IMMEDIATE_POSITION) { 79 logger.report(); 80 } else { 81 ListBuffer<LintLogger> loggers = loggersQueue.get(currentPos); 82 if (loggers == null) { 83 loggersQueue.put(currentPos, loggers = new ListBuffer<>()); 84 } 85 loggers.append(logger); 86 } 87 } 88 89 /**Invoke all {@link LintLogger}s that were associated with the provided {@code pos}. 90 */ flush(DiagnosticPosition pos)91 public void flush(DiagnosticPosition pos) { 92 ListBuffer<LintLogger> loggers = loggersQueue.get(pos); 93 if (loggers != null) { 94 for (LintLogger lintLogger : loggers) { 95 lintLogger.report(); 96 } 97 loggersQueue.remove(pos); 98 } 99 } 100 101 /**Sets the current position to the provided {@code currentPos}. {@link LintLogger}s 102 * passed to subsequent invocations of {@link #report(LintLogger) } will be associated 103 * with the given position. 104 */ setPos(DiagnosticPosition currentPos)105 public DiagnosticPosition setPos(DiagnosticPosition currentPos) { 106 DiagnosticPosition prevPosition = this.currentPos; 107 this.currentPos = currentPos; 108 return prevPosition; 109 } 110 111 /**{@link LintLogger}s passed to subsequent invocations of 112 * {@link #report(LintLogger) } will be invoked immediately. 113 */ immediate()114 public DiagnosticPosition immediate() { 115 return setPos(IMMEDIATE_POSITION); 116 } 117 118 private static final DiagnosticPosition IMMEDIATE_POSITION = new DiagnosticPosition() { 119 @Override 120 public JCTree getTree() { 121 Assert.error(); 122 return null; 123 } 124 125 @Override 126 public int getStartPosition() { 127 Assert.error(); 128 return -1; 129 } 130 131 @Override 132 public int getPreferredPosition() { 133 Assert.error(); 134 return -1; 135 } 136 137 @Override 138 public int getEndPosition(EndPosTable endPosTable) { 139 Assert.error(); 140 return -1; 141 } 142 }; 143 } 144