| // Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | package com.android.tools.r8; | 
 |  | 
 | import com.android.tools.r8.keepanno.annotations.KeepForApi; | 
 | import com.android.tools.r8.utils.StringUtils; | 
 | import java.util.ArrayList; | 
 | import java.util.List; | 
 |  | 
 | /** | 
 |  * Public utility for printing R8/D8 command line flags. | 
 |  * | 
 |  * <p>This utility can be used to support wrapping the compilers command-line interface. | 
 |  */ | 
 | @KeepForApi | 
 | public class ParseFlagPrinter { | 
 |  | 
 |   private final List<ParseFlagInfo> flags = new ArrayList<>(); | 
 |  | 
 |   private String prefix = "  "; | 
 |   private int helpColumn = 25; | 
 |   private String helpSeparator = " # "; | 
 |  | 
 |   // Formatting state. | 
 |   private StringBuilder builder = null; | 
 |   private int currentColumn = -1; | 
 |  | 
 |   // We use -1 to denote the unstarted line, otherwise we can't distinguish it when prefix is empty. | 
 |   private boolean isLineStarted() { | 
 |     return currentColumn >= 0; | 
 |   } | 
 |  | 
 |   private void append(String string) { | 
 |     assert isLineStarted(); | 
 |     builder.append(string); | 
 |     currentColumn += string.length(); | 
 |   } | 
 |  | 
 |   private void space(int space) { | 
 |     assert isLineStarted(); | 
 |     for (int i = 0; i < space; i++) { | 
 |       builder.append(' '); | 
 |     } | 
 |     currentColumn += space; | 
 |   } | 
 |  | 
 |   private void endLine() { | 
 |     assert isLineStarted(); | 
 |     builder.append(StringUtils.LINE_SEPARATOR); | 
 |     currentColumn = -1; | 
 |   } | 
 |  | 
 |   private void startLine() { | 
 |     assert !isLineStarted(); | 
 |     currentColumn = 0; | 
 |     append(prefix); | 
 |   } | 
 |  | 
 |   private void addFlagLine(String flagLine) { | 
 |     if (isLineStarted()) { | 
 |       endLine(); | 
 |     } | 
 |     startLine(); | 
 |     append(flagLine); | 
 |   } | 
 |  | 
 |   private void addHelpLine(String helpLine) { | 
 |     // If the current line is already past the point for printing help implicitly end the line. | 
 |     if (currentColumn > helpColumn) { | 
 |       endLine(); | 
 |     } | 
 |     if (!isLineStarted()) { | 
 |       startLine(); | 
 |     } | 
 |     int distanceToHelpColum = helpColumn - currentColumn; | 
 |     space(distanceToHelpColum); | 
 |     append(helpSeparator); | 
 |     append(helpLine); | 
 |     endLine(); | 
 |   } | 
 |  | 
 |   private void formatParseFlags() { | 
 |     for (ParseFlagInfo flag : flags) { | 
 |       addFlagLine(flag.getFlagFormat()); | 
 |       flag.getFlagFormatAlternatives().forEach(this::addFlagLine); | 
 |       flag.getFlagHelp().forEach(this::addHelpLine); | 
 |     } | 
 |   } | 
 |  | 
 |   public ParseFlagPrinter addFlags(List<ParseFlagInfo> flags) { | 
 |     this.flags.addAll(flags); | 
 |     return this; | 
 |   } | 
 |  | 
 |   /** Set a prefix which will be prepended to each line (flags and help lines). */ | 
 |   public ParseFlagPrinter setPrefix(String prefix) { | 
 |     this.prefix = prefix; | 
 |     return this; | 
 |   } | 
 |  | 
 |   /** Convenience method to set the prefix to be 'indent' number of spaces. */ | 
 |   public ParseFlagPrinter setIndent(int indent) { | 
 |     return setPrefix(" ".repeat(indent)); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Set the column at which the help information should start. | 
 |    * | 
 |    * <p>If a flag header extends past the end of the help column, then the help will start on a new | 
 |    * line at the point of the specified help column. | 
 |    */ | 
 |   public ParseFlagPrinter setHelpColumn(int helpColumn) { | 
 |     this.helpColumn = helpColumn; | 
 |     return this; | 
 |   } | 
 |  | 
 |   /** | 
 |    * Set the separator to use to split the help information from the flag info. | 
 |    * | 
 |    * <p>This is prefixed to every help line and thus extends the size of each help line. The help | 
 |    * separator will always start at exactly the help column ({@see setHelpColumn(int)}. | 
 |    */ | 
 |   public ParseFlagPrinter setHelpSeparator(String helpSeparator) { | 
 |     this.helpSeparator = helpSeparator; | 
 |     return this; | 
 |   } | 
 |  | 
 |   public void appendLinesToBuilder(StringBuilder builder) { | 
 |     assert this.builder == null; | 
 |     assert this.currentColumn == -1; | 
 |     this.builder = builder; | 
 |     formatParseFlags(); | 
 |     this.builder = null; | 
 |     this.currentColumn = -1; | 
 |   } | 
 |  | 
 |   public static void main(String[] args) { | 
 |     D8.main(new String[] {"--help"}); | 
 |   } | 
 | } |