/***
                     * NOTE: when we've failed to find change events for properties of untyped or Object-typed parents, we go
                     * ahead and generate code to create a runtime PropertyWatcher with no change events specified. The lack
                     * of change events tells the runtime PW to introspect RTTI to discover change events associated with the
                     * actual type of the actual value being assigned to the property.
                     * OTOH for strongly-typed properties, we still require change events to be reachable at compile time.
                     */
private void findEvents(Context context, String name, MultiName multiName, int pos, Watcher watcher, ReferenceValue ref)
    {
        String srcTypeName = null;
        if (watcher.isPartOfAnonObjectGraph())
        {
            srcTypeName = standardDefs.CLASS_OBJECTPROXY;
        }
        else if (! srcTypeStack.empty())
        {
            srcTypeName = srcTypeStack.peek();
        }
        Watcher parentWatcher = watcher.getParent();
        if ((parentWatcher != null) && parentWatcher.isOperation())
        {
            watcher.addChangeEvent("resultForBinding");
        }
        else if (srcTypeName != null)
        {
            AbcClass watchedClass = typeTable.getClass(srcTypeName);
            if (watchedClass != null)
            {
                if ( watchedClass.isSubclassOf(standardDefs.CLASS_OBJECTPROXY) )
                {
                    watcher.setPartOfAnonObjectGraph(true);
                }
                List metaData = watchedClass.getMetaData(BINDABLE, true);
                boolean foundEvents = addBindables(watcher, metaData);
                boolean foundSource = false;
                Variable variable = getVariable(context, watchedClass, ref, multiName);
                if (variable != null)
                {
                    metaData = variable.getMetaData(BINDABLE);
                    foundEvents = addBindables(watcher, metaData) || foundEvents;
                    metaData = variable.getMetaData(CHANGE_EVENT);
                    foundEvents = addChangeEvents(watcher, metaData) || foundEvents;
                    metaData = variable.getMetaData(NON_COMMITTING_CHANGE_EVENT);
                    foundEvents = addNonCommittingChangeEvents(watcher, metaData) || foundEvents;
                    // Object has a public static const variable names "length", which is
                    // some legacy compatibility crap left over from EMCA script 262, so
                    // we ignore it.
                    if (variable.isConst() &&
                        !(multiName.getLocalPart().equals("length") &&
                          variable.getDeclaringClassName().equals(SymbolTable.OBJECT)))
                    {
                        // We didn't really find any events, but we want
                        // to follow the same code path below as if we did.
                        foundEvents = true;
                        //    TODO will this ever be something besides a PropertyWatcher?
                        if (watcher instanceof PropertyWatcher)
                        {
                            ((PropertyWatcher) watcher).suppress();
                        }
                    }
                    // See comment above.
                    if (!(multiName.getLocalPart().equals("length") &&
                          variable.getDeclaringClassName().equals(SymbolTable.OBJECT)))
                    {
                        checkForStaticProperty(variable.isStatic(), watcher, srcTypeName);
                    }
                    foundSource = true;
                }
                if (!foundEvents)
                {
                    Method getter = getGetter(context, watchedClass, ref, multiName);
                    if (getter != null)
                    {
                        metaData = getter.getMetaData(BINDABLE);
                        foundEvents = addBindables(watcher, metaData) || foundEvents;
                        metaData = getter.getMetaData(CHANGE_EVENT);
                        foundEvents = addChangeEvents(watcher, metaData) || foundEvents;
                        metaData = getter.getMetaData(NON_COMMITTING_CHANGE_EVENT);
                        foundEvents = addNonCommittingChangeEvents( watcher, metaData) || foundEvents;
                        checkForStaticProperty(getter.isStatic(), watcher, srcTypeName);
                        foundSource = true;
                    }
                    Method setter = getSetter(context, watchedClass, ref, multiName);
                    if (setter != null)
                    {
                        metaData = setter.getMetaData(BINDABLE);
                        foundEvents = addBindables(watcher, metaData) || foundEvents;
                        metaData = setter.getMetaData(CHANGE_EVENT);
                        foundEvents = addChangeEvents(watcher, metaData) || foundEvents;
                        metaData = setter.getMetaData(NON_COMMITTING_CHANGE_EVENT);
                        foundEvents = addNonCommittingChangeEvents(watcher, metaData) || foundEvents;
                        checkForStaticProperty(setter.isStatic(), watcher, srcTypeName);
                        foundSource = true;
                    }
                    else
                    {
                        if (getter != null)
                        {
                            //    getters without setters are de facto const, use same bypass as above for const vars
                            foundEvents = true;
                        }
                    }
                }
                if (!foundSource)
                {
                    Method function = getMethod(context, watchedClass, ref, multiName);
                    if (function != null)
                    {
                        metaData = function.getMetaData(BINDABLE);
                        foundEvents = addBindables(watcher, metaData) || foundEvents;
                        metaData = function.getMetaData(CHANGE_EVENT);
                        foundEvents = addChangeEvents(watcher, metaData) || foundEvents;
                        metaData = function.getMetaData(NON_COMMITTING_CHANGE_EVENT);
                        foundEvents = addNonCommittingChangeEvents(watcher, metaData) || foundEvents;
                        foundSource = true;
                        if (!foundEvents && callExpressionStack.isEmpty())
                        {
                            foundEvents = true;
                            //    TODO will this ever be something besides a PropertyWatcher?
                            if (watcher instanceof PropertyWatcher)
                            {
                                ((PropertyWatcher)watcher).suppress();
                            }
                        }
                    }
                }
                if ((!foundSource) && watchedClass.isSubclassOf(standardDefs.CLASS_ABSTRACTSERVICE))
                {
                    watcher.setOperation(true);
                }
                else if (!foundEvents &&
                         !(watcher instanceof FunctionReturnWatcher) &&
                         !(watcher instanceof XMLWatcher) &&
                         !watcher.isOperation())
                {
                    /***
                     * NOTE: when we've failed to find change events for properties of untyped or Object-typed parents, we go
                     * ahead and generate code to create a runtime PropertyWatcher with no change events specified. The lack
                     * of change events tells the runtime PW to introspect RTTI to discover change events associated with the
                     * actual type of the actual value being assigned to the property.
                     * OTOH for strongly-typed properties, we still require change events to be reachable at compile time.
                     */
                    if (!(watchedClass.getName().equals(SymbolTable.OBJECT) || watchedClass.getName().equals(SymbolTable.NOTYPE)))
                    {
                        //    TODO do we still want this to be configurable?
                        if (showBindingWarnings)
                        {
                            context.localizedWarning2(pos, new UnableToDetectChanges(name));
                        }
                        //    TODO will this ever be something besides a PropertyWatcher?
                        if (watcher instanceof PropertyWatcher)
                        {
                            ((PropertyWatcher)watcher).suppress();
                        }
                    }
                }
            }
        }
    }
!watcher.isOperation())
{
/***
* NOTE: when we've failed to find change events for properties of untyped or Object-typed parents, we go
* ahead and generate code to create a runtime PropertyWatcher with no change events specified. The lack
* of change events tells the runtime PW to introspect RTTI to discover change events associated with the
* actual type of the actual value being assigned to the property.
* OTOH for strongly-typed properties, we still require change events to be reachable at compile time.
*/
if (!(watchedClass.getName().equals(SymbolTable.OBJECT) || watchedClass.getName().equals(SymbolTable.NOTYPE)))
{
}
if ((!foundSource) && watchedClass.isSubclassOf(standardDefs.CLASS_ABSTRACTSERVICE))
{
watcher.setOperation(true);
}
else if (!foundEvents &&
!(watcher instanceof FunctionReturnWatcher) &&
!(watcher instanceof XMLWatcher) &&
!watcher.isOperation())
{
/***
* NOTE: when we've failed to find change events for properties of untyped or Object-typed parents, we go
* ahead and generate code to create a runtime PropertyWatcher with no change events specified. The lack
* of change events tells the runtime PW to introspect RTTI to discover change events associated with the
* actual type of the actual value being assigned to the property.
* OTOH for strongly-typed properties, we still require change events to be reachable at compile time.
*/
if (!(watchedClass.getName().equals(SymbolTable.OBJECT) || watchedClass.getName().equals(SymbolTable.NOTYPE)))
{
// TODO do we still want this to be configurable?
if (showBindingWarnings)
{
context.localizedWarning2(pos, new UnableToDetectChanges(name));
}
// TODO will this ever be something besides a PropertyWatcher?
if (watcher instanceof PropertyWatcher)
{
if (!foundEvents && callExpressionStack.isEmpty())
{
foundEvents = true;
// TODO will this ever be something besides a PropertyWatcher?
if (watcher instanceof PropertyWatcher)
{
((PropertyWatcher)watcher).suppress();
}
}
}
}
if ((!foundSource) && watchedClass.isSubclassOf(standardDefs.CLASS_ABSTRACTSERVICE))
{
watcher.setOperation(true);
}
else if (!foundEvents &&
!(watcher instanceof FunctionReturnWatcher) &&
!(watcher instanceof XMLWatcher) &&
!watcher.isOperation())
{
/***
* NOTE: when we've failed to find change events for properties of untyped or Object-typed parents, we go
* ahead and generate code to create a runtime PropertyWatcher with no change events specified. The lack
* of change events tells the runtime PW to introspect RTTI to discover change events associated with the
* actual type of the actual value being assigned to the property.
* OTOH for strongly-typed properties, we still require change events to be reachable at compile time.
*/
if (!(watchedClass.getName().equals(SymbolTable.OBJECT) || watchedClass.getName().equals(SymbolTable.NOTYPE)))
{
// TODO do we still want this to be configurable?
if (showBindingWarnings)
{
context.localizedWarning2(pos, new UnableToDetectChanges(name));
}
// TODO will this ever be something besides a PropertyWatcher?
if (watcher instanceof PropertyWatcher)
{
((PropertyWatcher)watcher).suppress();
}
}
}
}
}
}