ExprModel { public void seal() { L.d("sealing model"); List<Expr> notifiableExpressions = new ArrayList<Expr>(); final ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); updateExpressions(modelAnalyzer); int counter = 0; final Iterable<Expr> observables = filterObservables(modelAnalyzer); List<String> flagMapping = new ArrayList<String>(); mObservables = new ArrayList<Expr>(); for (Expr expr : observables) { flagMapping.add(expr.getUniqueKey()); expr.setId(counter++); mObservables.add(expr); notifiableExpressions.add(expr); L.d("observable %s", expr.getUniqueKey()); } final Iterable<Expr> nonObservableIds = filterNonObservableIds(modelAnalyzer); for (Expr expr : nonObservableIds) { flagMapping.add(expr.getUniqueKey()); expr.setId(counter++); notifiableExpressions.add(expr); L.d("non-observable %s", expr.getUniqueKey()); } for (Expr expr : observables) { for (Expr parent : expr.getParents()) { if (parent.hasId()) { continue; } if (parent instanceof FieldAccessExpr) { FieldAccessExpr fae = (FieldAccessExpr) parent; L.d("checking field access expr %s. getter: %s", fae,fae.getGetter()); if (fae.getGetter() != null && fae.isDynamic() && fae.getGetter().canBeInvalidated()) { flagMapping.add(parent.getUniqueKey()); parent.setId(counter++); notifiableExpressions.add(parent); L.d("notifiable field %s : %s for %s : %s", parent.getUniqueKey(), Integer.toHexString(System.identityHashCode(parent)), expr.getUniqueKey(), Integer.toHexString(System.identityHashCode(expr))); } } } } for (Expr expr : mExprMap.values()) { if (expr instanceof FieldAccessExpr) { FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) expr; if (fieldAccessExpr.getTarget() instanceof ViewFieldExpr) { flagMapping.add(fieldAccessExpr.getUniqueKey()); fieldAccessExpr.setId(counter++); } } } L.d("list of binding expressions"); for (int i = 0; i < mBindingExpressions.size(); i++) { L.d("[%d] %s", i, mBindingExpressions.get(i)); } for (Expr expr : notifiableExpressions) { expr.enableDirectInvalidation(); } for (Expr expr : mExprMap.values()) { expr.getDependencies(); } mInvalidateAnyFlagIndex = counter ++; flagMapping.add("INVALIDATE ANY"); mInvalidateableFieldLimit = counter; BitSet invalidateableFlags = new BitSet(); for (int i = 0; i < mInvalidateableFieldLimit; i++) { invalidateableFlags.set(i, true); } for (Expr expr : mExprMap.values()) { if (expr.isConditional()) { L.d("requirement id for %s is %d", expr, counter); expr.setRequirementId(counter); flagMapping.add(expr.getUniqueKey() + FALSE_KEY_SUFFIX); flagMapping.add(expr.getUniqueKey() + TRUE_KEY_SUFFIX); counter += 2; } } BitSet conditionalFlags = new BitSet(); for (int i = mInvalidateableFieldLimit; i < counter; i++) { conditionalFlags.set(i, true); } mRequirementIdCount = (counter - mInvalidateableFieldLimit) / 2; for (Map.Entry<String, Expr> entry : mExprMap.entrySet()) { final Expr value = entry.getValue(); if (!value.hasId()) { value.setId(counter++); } } mFlagMapping = new String[flagMapping.size()]; flagMapping.toArray(mFlagMapping); mFlagBucketCount = 1 + (getTotalFlagCount() / FlagSet.sBucketSize); mInvalidateAnyFlags = new BitSet(); mInvalidateAnyFlags.set(mInvalidateAnyFlagIndex, true); for (Expr expr : mExprMap.values()) { expr.getShouldReadFlagsWithConditionals(); } for (Expr expr : mExprMap.values()) { expr.getResolvedType(); } mSealed = true; }  T register(T expr); ExprModelExt getExt(); int obtainCallbackId(); void setCurrentParserContext(ParserRuleContext currentParserContext); ParserRuleContext getCurrentParserContext(); Location getCurrentLocationInFile(); Map<String, Expr> getExprMap(); int size(); ComparisonExpr comparison(String op, Expr left, Expr right); InstanceOfExpr instanceOfOp(Expr expr, String type); FieldAccessExpr field(Expr parent, String name); FieldAccessExpr observableField(Expr parent, String name); MethodReferenceExpr methodReference(Expr parent, String name); SymbolExpr symbol(String text, Class type); TernaryExpr ternary(Expr pred, Expr ifTrue, Expr ifFalse); IdentifierExpr identifier(String name); StaticIdentifierExpr staticIdentifier(String name); BuiltInVariableExpr builtInVariable(String name, String type, String accessCode); ViewFieldExpr viewFieldExpr(BindingTarget bindingTarget); StaticIdentifierExpr staticIdentifierFor(final ModelClass modelClass); MethodCallExpr methodCall(Expr target, String name, List<Expr> args); MathExpr math(Expr left, String op, Expr right); TernaryExpr logical(Expr left, String op, Expr right); BitShiftExpr bitshift(Expr left, String op, Expr right); UnaryExpr unary(String op, Expr expr); Expr resourceExpr(BindingTarget target, String packageName, String resourceType,
            String resourceName, List<Expr> args); Expr bracketExpr(Expr variableExpr, Expr argExpr); Expr castExpr(String type, Expr expr); TwoWayListenerExpr twoWayListenerExpr(InverseBinding inverseBinding); List<Expr> getBindingExpressions(); StaticIdentifierExpr addImport(String alias, String type, Location location); Map<String, String> getImports(); Expr bindingExpr(Expr bindingExpr); void removeExpr(Expr expr); List<Expr> getObservables(); void seal(); int getFlagBucketCount(); int getTotalFlagCount(); int getInvalidateableFieldLimit(); String[] getFlagMapping(); String getFlag(int id); List<Expr> getPendingExpressions(); boolean markBitsRead(); static ArrayList<Expr> filterShouldRead(Iterable<Expr> exprs); Expr findFlagExpression(int flag); BitSet getInvalidateAnyBitSet(); int getInvalidateAnyFlagIndex(); Expr argListExpr(Iterable<Expr> expressions); void setCurrentLocationInFile(Location location); Expr listenerExpr(Expr expression, String name, ModelClass listenerType,
            ModelMethod listenerMethod); FieldAssignmentExpr assignment(Expr target, String name, Expr value); Map<String, CallbackWrapper> getCallbackWrappers(); CallbackWrapper callbackWrapper(ModelClass klass, ModelMethod method); LambdaExpr lambdaExpr(Expr expr, CallbackExprModel callbackExprModel); IdentifierExpr findIdentifier(String name);  }
@Test public void testStaticMethodOfInstance() { MockLayoutBinder lb = new MockLayoutBinder(); mExprModel = lb.getModel(); lb.addVariable("user", User.class.getCanonicalName(), null); MethodCallExpr methodCall = parse(lb, "user.ourStaticMethod()", MethodCallExpr.class); assertTrue(methodCall.isDynamic()); mExprModel.seal(); final Expr child = methodCall.getTarget(); assertTrue(child instanceof StaticIdentifierExpr); StaticIdentifierExpr id = (StaticIdentifierExpr) child; assertEquals(id.getResolvedType().getCanonicalName(), User.class.getCanonicalName()); }