<lambda>null1 package com.android.codegen
2 
3 import com.github.javaparser.JavaParser
4 import java.io.File
5 
6 
7 const val THIS_SCRIPT_LOCATION = ""
8 const val GENERATED_WARNING_PREFIX = "Code below generated by $CODEGEN_NAME"
9 const val GENERATED_END = "// End of generated code"
10 const val INDENT_SINGLE = "    "
11 
12 val PRIMITIVE_TYPES = listOf("byte", "short", "int", "long", "char", "float", "double", "boolean")
13 val PRIMITIVE_ARRAY_TYPES = listOf("byte[]", "short[]", "int[]", "long[]", "char[]", "float[]", "double[]", "boolean[]")
14 val BOXED_PRIMITIVE_TYPES = PRIMITIVE_TYPES.map { it.capitalize() } - "Int" + "Integer" - "Char" + "Character"
15 
16 val BUILTIN_SPECIAL_PARCELLINGS = listOf("Pattern")
17 
18 const val FLAG_BUILDER_PROTECTED_SETTERS = "--builder-protected-setters"
19 const val FLAG_NO_FULL_QUALIFIERS = "--no-full-qualifiers"
20 
21 val JAVA_PARSER = JavaParser()
22 
23 /** @see [FeatureFlag] */
24 val USAGE = """
25 Usage: $CODEGEN_NAME [--[PREFIX-]FEATURE...] JAVAFILE
26 
27 Generates boilerplade parcelable/data class code at the bottom of JAVAFILE, based o fields' declaration in the given JAVAFILE's top-level class
28 
29 FEATURE represents some generatable code, and can be among:
featurenull30 ${FeatureFlag.values().map { feature ->
31     "  ${feature.kebabCase}" to feature.desc
32 }.columnize(" - ")}
33 
34 And PREFIX can be:
35   <empty> - request to generate the feature
36     no    - suppress generation of the feature
37   hidden  - request to generate the feature with @hide
38 
39 Extra options:
40   --help        - view this help
41   --update-only - auto-detect flags from the previously auto-generated comment within the file
42   $FLAG_NO_FULL_QUALIFIERS
43                 - when referring to classes don't use package name prefix; handy with IDE auto-import
44   $FLAG_BUILDER_PROTECTED_SETTERS
45                 - make builder's setters protected to expose them as public in a subclass on a whitelist basis
46 
47 
48 Special field modifiers and annotations:
49   transient                 - ignore the field completely
50   @Nullable                 - support null value when parcelling, and never throw on null input
51   @NonNull                  - throw on null input and don't parcel the nullness bit for the field
52   @DataClass.Enum           - parcel field as an enum value by ordinal
53   @DataClass.PluralOf(..)   - provide a singular version of a collection field name to be used in the builder's 'addFoo(..)'
54   @DataClass.ParcelWith(..) - provide a custom Parcelling class, specifying the custom (un)parcelling logic for this field
55   = <initializer>;          - provide default value and never throw if this field was not provided e.g. when using builder
56   /** ... */                - copy given javadoc on field's getters/setters/constructor params/builder setters etc.
57   @hide (in javadoc)        - force field's getters/setters/withers/builder setters to be @hide-den if generated
58 
59 
60 Special methods/etc. you can define:
61 
62   <any auto-generatable method>
63       For any method to be generated, if a method with same name and argument types is already
64       defined, than that method will not be generated.
65       This allows you to override certain details on granular basis.
66 
67   void onConstructed()
68       Will be called in constructor, after all the fields have been initialized.
69       This is a good place to put any custom validation logic that you may have
70 
71   static class $CANONICAL_BUILDER_CLASS extends $BASE_BUILDER_CLASS
72       If a class extending $BASE_BUILDER_CLASS is specified, generated builder's setters will
73       return the provided $CANONICAL_BUILDER_CLASS type.
74       $BASE_BUILDER_CLASS's constructor(s) will be package-private to encourage using $CANONICAL_BUILDER_CLASS instead
75       This allows you to extend the generated builder, adding or overriding any methods you may want
76 
77 
78 In addition, for any field mMyField(or myField) of type FieldType you can define the following methods:
79 
80   void parcelMyField(Parcel dest, int flags)
81       Allows you to provide custom logic for storing mMyField into a Parcel
82 
83   static FieldType unparcelMyField(Parcel in)
84       Allows you to provide custom logic to deserialize the value of mMyField from a Parcel
85 
86   String myFieldToString()
87       Allows you to provide a custom toString representation of mMyField's value
88 
89   FieldType lazyInitMyField()
90       Requests a lazy initialization in getMyField(), with the provided method being the constructor
91       You may additionally mark the fields as volatile to cause this to generate a thread-safe
92       double-check locking lazy initialization
93 
94   FieldType defaultMyField()
95       Allows you to provide a default value to initialize the field to, in case an explicit one
96       was not provided.
97       This is an alternative to providing a field initializer that, unlike the initializer,
98       you can use with final fields.
99 
100 Version: $CODEGEN_VERSION
101 
102 Questions? Feedback?
103 Contact: eugenesusla@
104 Bug/feature request: http://go/codegen-bug
105 
106 Slides: http://go/android-codegen
107 In-depth example: http://go/SampleDataClass
108 """
109 
110 fun main(args: Array<String>) {
111     if (args.contains("--help")) {
112         println(USAGE)
113         System.exit(0)
114     }
115     if (args.contains("--version")) {
116         println(CODEGEN_VERSION)
117         System.exit(0)
118     }
119     val file = File(args.last()).absoluteFile
120     val sourceLisnesOriginal = file.readLines()
121     val sourceLinesNoClosingBrace = sourceLisnesOriginal.dropLastWhile {
122         it.startsWith("}") || it.all(Char::isWhitespace)
123     }
124     val cliArgs = handleUpdateFlag(args, sourceLinesNoClosingBrace)
125 
126     val fileInfo = FileInfo(sourceLisnesOriginal, cliArgs, file)
127     fileInfo.main()
128     file.writeText(fileInfo.stringBuilder.toString().mapLines { trimEnd() })
129 }
130 
handleUpdateFlagnull131 private fun handleUpdateFlag(cliArgs: Array<String>, sourceLines: List<String>): Array<String> {
132     if ("--update-only" in cliArgs
133             && sourceLines.none { GENERATED_WARNING_PREFIX in it || it.startsWith("@DataClass") }) {
134         System.exit(0)
135     }
136     return cliArgs - "--update-only"
137 }
138