gt:             if (!lines.isEmpty()) {
context: /*
   * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  package com.sun.tools.javac.util;
  
  import java.util.EnumMap;
  import java.util.EnumSet;
  import java.util.HashMap;
  import java.util.LinkedHashMap;
  import java.util.Locale;
  import java.util.Map;
  
  import com.sun.tools.javac.code.Kinds;
  import com.sun.tools.javac.code.Printer;
  import com.sun.tools.javac.code.Symbol;
  import com.sun.tools.javac.code.Symbol.*;
  import com.sun.tools.javac.code.Symtab;
  import com.sun.tools.javac.code.Type;
  import com.sun.tools.javac.code.Type.*;
  import com.sun.tools.javac.code.Types;
  
  import static com.sun.tools.javac.code.TypeTag.*;
  import static com.sun.tools.javac.code.Flags.*;
  import static com.sun.tools.javac.util.LayoutCharacters.*;
  import static com.sun.tools.javac.util.RichDiagnosticFormatter.RichConfiguration.*;
  
  /**
   * A rich diagnostic formatter is a formatter that provides better integration
   * with javac's type system. A diagostic is first preprocessed in order to keep
   * track of each types/symbols in it; after these informations are collected,
   * the diagnostic is rendered using a standard formatter, whose type/symbol printer
   * has been replaced by a more refined version provided by this rich formatter.
   * The rich formatter currently enables three different features: (i) simple class
   * names - that is class names are displayed used a non qualified name (thus
   * omitting package info) whenever possible - (ii) where clause list - a list of
   * additional subdiagnostics that provide specific info about type-variables,
   * captured types, intersection types that occur in the diagnostic that is to be
   * formatted and (iii) type-variable disambiguation - when the diagnostic refers
   * to two different type-variables with the same name, their representation is
   * disambiguated by appending an index to the type variable name.
   *
   * <p><b>This is NOT part of any supported API.
   * If you write code that depends on this, you do so at your own risk.
   * This code and its internal interfaces are subject to change or
   * deletion without notice.</b>
   */
  public class RichDiagnosticFormatter extends
          ForwardingDiagnosticFormatter<JCDiagnostic, AbstractDiagnosticFormatter> {
  
      final Symtab syms;
      final Types types;
      final JCDiagnostic.Factory diags;
      final JavacMessages messages;
  
      /* name simplifier used by this formatter */
      protected ClassNameSimplifier nameSimplifier;
  
      /* type/symbol printer used by this formatter */
      private RichPrinter printer;
  
      /* map for keeping track of a where clause associated to a given type */
      Map<WhereClauseKind, Map<Type, JCDiagnostic>> whereClauses;
  
      /** Get the DiagnosticFormatter instance for this context. */
      public static RichDiagnosticFormatter instance(Context context) {
          RichDiagnosticFormatter instance = context.get(RichDiagnosticFormatter.class);
          if (instance == null)
              instance = new RichDiagnosticFormatter(context);
          return instance;
      }
  
      protected RichDiagnosticFormatter(Context context) {
          super((AbstractDiagnosticFormatter)Log.instance(context).getDiagnosticFormatter());
          setRichPrinter(new RichPrinter());
          this.syms = Symtab.instance(context);
          this.diags = JCDiagnostic.Factory.instance(context);
          this.types = Types.instance(context);
          this.messages = JavacMessages.instance(context);
          whereClauses = new EnumMap<WhereClauseKind, Map<Type, JCDiagnostic>>(WhereClauseKind.class);
          configuration = new RichConfiguration(Options.instance(context), formatter);
          for (WhereClauseKind kind : WhereClauseKind.values())
              whereClauses.put(kind, new LinkedHashMap<Type, JCDiagnostic>());
      }
  
      @Override
      public String format(JCDiagnostic diag, Locale l) {
          StringBuilder sb = new StringBuilder();
          nameSimplifier = new ClassNameSimplifier();
          for (WhereClauseKind kind : WhereClauseKind.values())
              whereClauses.get(kind).clear();
          preprocessDiagnostic(diag);
          sb.append(formatter.format(diag, l));
          if (getConfiguration().isEnabled(RichFormatterFeature.WHERE_CLAUSES)) {
              List<JCDiagnostic> clauses = getWhereClauses();
              String indent = formatter.isRaw() ? "" :
                  formatter.indentString(DetailsInc);
              for (JCDiagnostic d : clauses) {
                  String whereClause = formatter.format(d, l);
                  if (whereClause.length() > 0) {
                      sb.append('\n' + indent + whereClause);
                  }
              }
          }
          return sb.toString();
      }
  
      /**
       * Sets the type/symbol printer used by this formatter.
       * @param printer the rich printer to be set
       */
      protected void setRichPrinter(RichPrinter printer) {
          this.printer = printer;
          formatter.setPrinter(printer);
      }
  
      /**
       * Gets the type/symbol printer used by this formatter.
       * @return type/symbol rich printer
       */
      protected RichPrinter getRichPrinter() {
          return printer;
      }
  
      /**
       * Preprocess a given diagnostic by looking both into its arguments and into
       * its subdiagnostics (if any). This preprocessing is responsible for
       * generating info corresponding to features like where clauses, name
       * simplification, etc.
       *
       * @param diag the diagnostic to be preprocessed
       */
      protected void preprocessDiagnostic(JCDiagnostic diag) {
          for (Object o : diag.getArgs()) {
              if (o != null) {
                  preprocessArgument(o);
              }
          }
          if (diag.isMultiline()) {
              for (JCDiagnostic d : diag.getSubdiagnostics())
                  preprocessDiagnostic(d);
          }
      }
  
      /**
       * Preprocess a diagnostic argument. A type/symbol argument is
       * preprocessed by specialized type/symbol preprocessors.
       *
       * @param arg the argument to be translated
       */
      protected void preprocessArgument(Object arg) {
          if (arg instanceof Type) {
              preprocessType((Type)arg);
          }
          else if (arg instanceof Symbol) {
              preprocessSymbol((Symbol)arg);
          }
          else if (arg instanceof JCDiagnostic) {
              preprocessDiagnostic((JCDiagnostic)arg);
          }
          else if (arg instanceof Iterable<?>) {
              for (Object o : (Iterable<?>)arg) {
                  preprocessArgument(o);
              }
          }
      }
  
      /**
       * Build a list of multiline diagnostics containing detailed info about
       * type-variables, captured types, and intersection types
       *
       * @return where clause list
       */
      protected List<JCDiagnostic> getWhereClauses() {
          List<JCDiagnostic> clauses = List.nil();
          for (WhereClauseKind kind : WhereClauseKind.values()) {
              List<JCDiagnostic> lines = List.nil();
              for (Map.Entry<Type, JCDiagnostic> entry : whereClauses.get(kind).entrySet()) {
                  lines = lines.prepend(entry.getValue());
              }
  