main.dart 5.94 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io' hide Platform;

import 'package:args/args.dart';
8
import 'package:path/path.dart' as path;
9 10 11 12 13
import 'package:platform/platform.dart';

import 'configuration.dart';
import 'snippets.dart';

14
const String _kSerialOption = 'serial';
15
const String _kElementOption = 'element';
16
const String _kHelpOption = 'help';
17 18
const String _kInputOption = 'input';
const String _kLibraryOption = 'library';
19
const String _kOutputOption = 'output';
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
const String _kPackageOption = 'package';
const String _kTemplateOption = 'template';
const String _kTypeOption = 'type';

/// Generates snippet dartdoc output for a given input, and creates any sample
/// applications needed by the snippet.
void main(List<String> argList) {
  const Platform platform = LocalPlatform();
  final Map<String, String> environment = platform.environment;
  final ArgParser parser = ArgParser();
  final List<String> snippetTypes =
      SnippetType.values.map<String>((SnippetType type) => getEnumName(type)).toList();
  parser.addOption(
    _kTypeOption,
    defaultsTo: getEnumName(SnippetType.application),
    allowed: snippetTypes,
    allowedHelp: <String, String>{
      getEnumName(SnippetType.application):
          'Produce a code snippet complete with embedding the sample in an '
          'application template.',
      getEnumName(SnippetType.sample):
          'Produce a nicely formatted piece of sample code. Does not embed the '
42
          'sample into an application template.',
43 44 45 46 47 48 49 50
    },
    help: 'The type of snippet to produce.',
  );
  parser.addOption(
    _kTemplateOption,
    defaultsTo: null,
    help: 'The name of the template to inject the code into.',
  );
51 52 53 54 55
  parser.addOption(
    _kOutputOption,
    defaultsTo: null,
    help: 'The output path for the generated snippet application. Overrides '
        'the naming generated by the --package/--library/--element arguments. '
56
        'Metadata will be written alongside in a .json file. '
57 58
        'The basename of this argument is used as the ID',
  );
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
  parser.addOption(
    _kInputOption,
    defaultsTo: environment['INPUT'],
    help: 'The input file containing the snippet code to inject.',
  );
  parser.addOption(
    _kPackageOption,
    defaultsTo: environment['PACKAGE_NAME'],
    help: 'The name of the package that this snippet belongs to.',
  );
  parser.addOption(
    _kLibraryOption,
    defaultsTo: environment['LIBRARY_NAME'],
    help: 'The name of the library that this snippet belongs to.',
  );
  parser.addOption(
    _kElementOption,
    defaultsTo: environment['ELEMENT_NAME'],
    help: 'The name of the element that this snippet belongs to.',
  );
79 80 81 82 83
  parser.addOption(
    _kSerialOption,
    defaultsTo: environment['INVOCATION_INDEX'],
    help: 'A unique serial number for this snippet tool invocation.',
  );
84 85 86 87 88 89
  parser.addFlag(
    _kHelpOption,
    defaultsTo: false,
    negatable: false,
    help: 'Prints help documentation for this command',
  );
90 91 92

  final ArgResults args = parser.parse(argList);

93 94 95 96 97
  if (args[_kHelpOption]) {
    stderr.writeln(parser.usage);
    exit(0);
  }

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
  final SnippetType snippetType = SnippetType.values
      .firstWhere((SnippetType type) => getEnumName(type) == args[_kTypeOption], orElse: () => null);
  assert(snippetType != null, "Unable to find '${args[_kTypeOption]}' in SnippetType enum.");

  if (args[_kInputOption] == null) {
    stderr.writeln(parser.usage);
    errorExit('The --$_kInputOption option must be specified, either on the command '
        'line, or in the INPUT environment variable.');
  }

  final File input = File(args['input']);
  if (!input.existsSync()) {
    errorExit('The input file ${input.path} does not exist.');
  }

  String template;
  if (snippetType == SnippetType.application) {
    if (args[_kTemplateOption] == null || args[_kTemplateOption].isEmpty) {
      stderr.writeln(parser.usage);
      errorExit('The --$_kTemplateOption option must be specified on the command '
          'line for application snippets.');
    }
    template = args[_kTemplateOption].toString().replaceAll(RegExp(r'.tmpl$'), '');
  }

123 124 125
  final String packageName = args[_kPackageOption] != null && args[_kPackageOption].isNotEmpty ? args[_kPackageOption] : null;
  final String libraryName = args[_kLibraryOption] != null && args[_kLibraryOption].isNotEmpty ? args[_kLibraryOption] : null;
  final String elementName = args[_kElementOption] != null && args[_kElementOption].isNotEmpty ? args[_kElementOption] : null;
126
  final String serial = args[_kSerialOption] != null && args[_kSerialOption].isNotEmpty ? args[_kSerialOption] : null;
127
  final List<String> id = <String>[];
128 129 130
  if (args[_kOutputOption] != null) {
    id.add(path.basename(path.basenameWithoutExtension(args[_kOutputOption])));
  } else {
131 132
    if (packageName != null && packageName != 'flutter') {
      id.add(packageName);
133
    }
134 135
    if (libraryName != null) {
      id.add(libraryName);
136
    }
137 138
    if (elementName != null) {
      id.add(elementName);
139
    }
140 141 142
    if (serial != null) {
      id.add(serial);
    }
143 144
    if (id.isEmpty) {
      errorExit('Unable to determine ID. At least one of --$_kPackageOption, '
145 146
          '--$_kLibraryOption, --$_kElementOption, -$_kSerialOption, or the environment variables '
          'PACKAGE_NAME, LIBRARY_NAME, ELEMENT_NAME, or INVOCATION_INDEX must be non-empty.');
147
    }
148 149 150 151 152 153 154 155
  }

  final SnippetGenerator generator = SnippetGenerator();
  stdout.write(generator.generate(
    input,
    snippetType,
    template: template,
    id: id.join('.'),
156
    output: args[_kOutputOption] != null ? File(args[_kOutputOption]) : null,
157 158
    metadata: <String, Object>{
      'sourcePath': environment['SOURCE_PATH'],
159 160 161
      'sourceLine': environment['SOURCE_LINE'] != null
          ? int.tryParse(environment['SOURCE_LINE'])
          : null,
162
      'serial': serial,
163 164 165 166
      'package': packageName,
      'library': libraryName,
      'element': elementName,
    },
167
  ));
168

169 170
  exit(0);
}