• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.databinding.tool;
18 
19 import org.antlr.v4.runtime.misc.Nullable;
20 
21 import android.databinding.tool.expr.Dependency;
22 import android.databinding.tool.expr.Expr;
23 import android.databinding.tool.expr.ExprModel;
24 import android.databinding.tool.expr.ExprModel.ResolveListenersCallback;
25 import android.databinding.tool.expr.IdentifierExpr;
26 import android.databinding.tool.processing.Scope;
27 import android.databinding.tool.processing.scopes.FileScopeProvider;
28 import android.databinding.tool.store.Location;
29 import android.databinding.tool.store.ResourceBundle;
30 import android.databinding.tool.store.ResourceBundle.BindingTargetBundle;
31 import android.databinding.tool.util.Preconditions;
32 import android.databinding.tool.writer.LayoutBinderWriter;
33 import android.databinding.tool.writer.WriterPackage;
34 
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.Comparator;
38 import java.util.HashMap;
39 import java.util.List;
40 
41 /**
42  * Keeps all information about the bindings per layout file
43  */
44 public class LayoutBinder implements ResolveListenersCallback, FileScopeProvider {
45     private static final Comparator<BindingTarget> COMPARE_FIELD_NAME = new Comparator<BindingTarget>() {
46         @Override
47         public int compare(BindingTarget first, BindingTarget second) {
48             final String fieldName1 = WriterPackage.getFieldName(first);
49             final String fieldName2 = WriterPackage.getFieldName(second);
50             return fieldName1.compareTo(fieldName2);
51         }
52     };
53 
54     /*
55     * val pkg: String, val projectPackage: String, val baseClassName: String,
56         val layoutName:String, val lb: LayoutExprBinding*/
57     private final ExprModel mExprModel;
58     private final ExpressionParser mExpressionParser;
59     private final List<BindingTarget> mBindingTargets;
60     private final List<BindingTarget> mSortedBindingTargets;
61     private String mModulePackage;
62     private final HashMap<String, String> mUserDefinedVariables = new HashMap<String, String>();
63 
64     private LayoutBinderWriter mWriter;
65     private ResourceBundle.LayoutFileBundle mBundle;
66     private static final String[] sJavaLangClasses = {
67             "Deprecated",
68             "Override",
69             "SafeVarargs",
70             "SuppressWarnings",
71             "Appendable",
72             "AutoCloseable",
73             "CharSequence",
74             "Cloneable",
75             "Comparable",
76             "Iterable",
77             "Readable",
78             "Runnable",
79             "Thread.UncaughtExceptionHandler",
80             "Boolean",
81             "Byte",
82             "Character",
83             "Character.Subset",
84             "Character.UnicodeBlock",
85             "Class",
86             "ClassLoader",
87             "Compiler",
88             "Double",
89             "Enum",
90             "Float",
91             "InheritableThreadLocal",
92             "Integer",
93             "Long",
94             "Math",
95             "Number",
96             "Object",
97             "Package",
98             "Process",
99             "ProcessBuilder",
100             "Runtime",
101             "RuntimePermission",
102             "SecurityManager",
103             "Short",
104             "StackTraceElement",
105             "StrictMath",
106             "String",
107             "StringBuffer",
108             "StringBuilder",
109             "System",
110             "Thread",
111             "ThreadGroup",
112             "ThreadLocal",
113             "Throwable",
114             "Void",
115             "Thread.State",
116             "ArithmeticException",
117             "ArrayIndexOutOfBoundsException",
118             "ArrayStoreException",
119             "ClassCastException",
120             "ClassNotFoundException",
121             "CloneNotSupportedException",
122             "EnumConstantNotPresentException",
123             "Exception",
124             "IllegalAccessException",
125             "IllegalArgumentException",
126             "IllegalMonitorStateException",
127             "IllegalStateException",
128             "IllegalThreadStateException",
129             "IndexOutOfBoundsException",
130             "InstantiationException",
131             "InterruptedException",
132             "NegativeArraySizeException",
133             "NoSuchFieldException",
134             "NoSuchMethodException",
135             "NullPointerException",
136             "NumberFormatException",
137             "ReflectiveOperationException",
138             "RuntimeException",
139             "SecurityException",
140             "StringIndexOutOfBoundsException",
141             "TypeNotPresentException",
142             "UnsupportedOperationException",
143             "AbstractMethodError",
144             "AssertionError",
145             "ClassCircularityError",
146             "ClassFormatError",
147             "Error",
148             "ExceptionInInitializerError",
149             "IllegalAccessError",
150             "IncompatibleClassChangeError",
151             "InstantiationError",
152             "InternalError",
153             "LinkageError",
154             "NoClassDefFoundError",
155             "NoSuchFieldError",
156             "NoSuchMethodError",
157             "OutOfMemoryError",
158             "StackOverflowError",
159             "ThreadDeath",
160             "UnknownError",
161             "UnsatisfiedLinkError",
162             "UnsupportedClassVersionError",
163             "VerifyError",
164             "VirtualMachineError",
165     };
166 
LayoutBinder(ResourceBundle.LayoutFileBundle layoutBundle)167     public LayoutBinder(ResourceBundle.LayoutFileBundle layoutBundle) {
168         try {
169             Scope.enter(this);
170             mExprModel = new ExprModel();
171             mExpressionParser = new ExpressionParser(mExprModel);
172             mBindingTargets = new ArrayList<BindingTarget>();
173             mBundle = layoutBundle;
174             mModulePackage = layoutBundle.getModulePackage();
175             // copy over data.
176             for (ResourceBundle.NameTypeLocation variable : mBundle.getVariables()) {
177                 addVariable(variable.name, variable.type, variable.location);
178             }
179 
180             for (ResourceBundle.NameTypeLocation userImport : mBundle.getImports()) {
181                 mExprModel.addImport(userImport.name, userImport.type, userImport.location);
182             }
183             for (String javaLangClass : sJavaLangClasses) {
184                 mExprModel.addImport(javaLangClass, "java.lang." + javaLangClass, null);
185             }
186             for (BindingTargetBundle targetBundle : mBundle.getBindingTargetBundles()) {
187                 try {
188                     Scope.enter(targetBundle);
189                     final BindingTarget bindingTarget = createBindingTarget(targetBundle);
190                     for (BindingTargetBundle.BindingBundle bindingBundle : targetBundle
191                             .getBindingBundleList()) {
192                         bindingTarget.addBinding(bindingBundle.getName(),
193                                 parse(bindingBundle.getExpr(), bindingBundle.getValueLocation()));
194                     }
195                     bindingTarget.resolveMultiSetters();
196                 } finally {
197                     Scope.exit();
198                 }
199             }
200             mSortedBindingTargets = new ArrayList<BindingTarget>(mBindingTargets);
201             Collections.sort(mSortedBindingTargets, COMPARE_FIELD_NAME);
202         } finally {
203             Scope.exit();
204         }
205     }
206 
resolveWhichExpressionsAreUsed()207     public void resolveWhichExpressionsAreUsed() {
208         List<Expr> used = new ArrayList<Expr>();
209         for (BindingTarget target : mBindingTargets) {
210             for (Binding binding : target.getBindings()) {
211                 binding.getExpr().setIsUsed(true);
212                 used.add(binding.getExpr());
213             }
214         }
215         while (!used.isEmpty()) {
216             Expr e = used.remove(used.size() - 1);
217             for (Dependency dep : e.getDependencies()) {
218                 if (!dep.getOther().isUsed()) {
219                     used.add(dep.getOther());
220                     dep.getOther().setIsUsed(true);
221                 }
222             }
223         }
224     }
225 
addVariable(String name, String type, Location location)226     public IdentifierExpr addVariable(String name, String type, Location location) {
227         Preconditions.check(!mUserDefinedVariables.containsKey(name),
228                 "%s has already been defined as %s", name, type);
229         final IdentifierExpr id = mExprModel.identifier(name);
230         id.setUserDefinedType(type);
231         id.enableDirectInvalidation();
232         if (location != null) {
233             id.addLocation(location);
234         }
235         mUserDefinedVariables.put(name, type);
236         return id;
237     }
238 
getUserDefinedVariables()239     public HashMap<String, String> getUserDefinedVariables() {
240         return mUserDefinedVariables;
241     }
242 
createBindingTarget(ResourceBundle.BindingTargetBundle targetBundle)243     public BindingTarget createBindingTarget(ResourceBundle.BindingTargetBundle targetBundle) {
244         final BindingTarget target = new BindingTarget(targetBundle);
245         mBindingTargets.add(target);
246         target.setModel(mExprModel);
247         return target;
248     }
249 
parse(String input, @Nullable Location locationInFile)250     public Expr parse(String input, @Nullable Location locationInFile) {
251         final Expr parsed = mExpressionParser.parse(input, locationInFile);
252         parsed.setBindingExpression(true);
253         return parsed;
254     }
255 
getBindingTargets()256     public List<BindingTarget> getBindingTargets() {
257         return mBindingTargets;
258     }
259 
getSortedTargets()260     public List<BindingTarget> getSortedTargets() {
261         return mSortedBindingTargets;
262     }
263 
isEmpty()264     public boolean isEmpty() {
265         return mExprModel.size() == 0;
266     }
267 
getModel()268     public ExprModel getModel() {
269         return mExprModel;
270     }
271 
ensureWriter()272     private void ensureWriter() {
273         if (mWriter == null) {
274             mWriter = new LayoutBinderWriter(this);
275         }
276     }
277 
sealModel()278     public void sealModel() {
279         mExprModel.seal(this);
280     }
281 
writeViewBinderBaseClass(boolean forLibrary)282     public String writeViewBinderBaseClass(boolean forLibrary) {
283         ensureWriter();
284         return mWriter.writeBaseClass(forLibrary);
285     }
286 
writeViewBinder(int minSdk)287     public String writeViewBinder(int minSdk) {
288         ensureWriter();
289         Preconditions.checkNotNull(getPackage(), "package cannot be null");
290         Preconditions.checkNotNull(getClassName(), "base class name cannot be null");
291         return mWriter.write(minSdk);
292     }
293 
getPackage()294     public String getPackage() {
295         return mBundle.getBindingClassPackage();
296     }
297 
isMerge()298     public boolean isMerge() {
299         return mBundle.isMerge();
300     }
301 
getModulePackage()302     public String getModulePackage() {
303         return mModulePackage;
304     }
305 
getLayoutname()306     public String getLayoutname() {
307         return mBundle.getFileName();
308     }
309 
getImplementationName()310     public String getImplementationName() {
311         if (hasVariations()) {
312             return mBundle.getBindingClassName() + mBundle.getConfigName() + "Impl";
313         } else {
314             return mBundle.getBindingClassName();
315         }
316     }
317 
getClassName()318     public String getClassName() {
319         return mBundle.getBindingClassName();
320     }
321 
getTag()322     public String getTag() {
323         return mBundle.getDirectory() + "/" + mBundle.getFileName();
324     }
325 
hasVariations()326     public boolean hasVariations() {
327         return mBundle.hasVariations();
328     }
329 
330     @Override
resolveListeners()331     public void resolveListeners() {
332         for (BindingTarget target : mBindingTargets) {
333             for (Binding binding : target.getBindings()) {
334                 binding.resolveListeners();
335             }
336         }
337     }
338 
339     @Override
provideScopeFilePath()340     public String provideScopeFilePath() {
341         return mBundle.getAbsoluteFilePath();
342     }
343 }
344