Code model packages

com.adobe.flexbuilder.codemodel.common

Miscellaneous classes that don't fit into any of the other packages.

The most important of these is CMFactory, which is the class that provides access to the singleton instances of IProjectManager, ISwcManager, IRegistrar, and others.

com.adobe.flexbuilder.codemodel.project

Code model projects and listeners.

When the user opens the first file in an ActionScript or Flex project, the code model creates a code model project for it, reading all of the relevant ActionScript and MXML documents and SWC files in the project, its linked folders, and its class and library paths. (You can force a project to open before this point by using the IRegistrar class.). From that point on, you can retrieve an IProject from the IProjectManager and use it to find out about the contents of the project.

com.adobe.flexbuilder.codemodel.indices

Various indices that provide interesting views on the saved data in the project.

The "name" indices (like IClassNameIndex and IVariableNameIndex) let you look up definitions by name. IEventAttributeIndex and IStyleAttributeIndex cache information about metadata attributes (e.g. [Style(name="color")] and [Event(name="click")] that exist in source files. And ITagInformationIndex and IVisibleComponentIndex let you examine the components and component properties that are implied by the ActionScript classes and MXML components in the project. With Flex Builder 3, there is now an ISearchIndex that enables reference and declaration detection.

The indices are updated whenever you save a file. If the user has changed a file but has not yet saved it, the changes will not yet be reflected in the indices.

com.adobe.flexbuilder.codemodel.definitions and com.adobe.flexbuilder.codemodel.definitions.metadata

Definitions and scopes.

Definitions include packages, classes, interfaces, variables, functions, and certain metadata (Style, Event and Effect tags). You can retrieve the definitions in a project in several ways. Various indices provide access to lists of definitions or allow you to look them up by qualified name (e.g. mx.core.Button) or short name (Button). IClasses or IInterfaces know how to return their members. IVariables and IFunctions can resolve their types to definitions. IASScopes can return lists of definitions in scope. IExpressionNodes can evaluate themselves and provide a definition.

There is a scope for each {} block in a file (including function bodies, class bodies, and so on). There is also a file-level scope for each file in the project and a project-level scope that holds cross-file definitions. Scopes keep track of which definitions are available where.

ASDefinitionFilter allows you to control how to search when looking for definitions. You will usually want to use one of the various static "create" methods to create a reasonable definition filter.

com.adobe.flexbuilder.codemodel.tree

ActionScript parse tree nodes.

MXML and ActionScript files both have ActionScript parse trees. In the case of an MXML document, the MXML is translated into an equivalent ActionScript. Parts of the MXML document that are "ActionScript-y", like <mx:Script> tags, event attributes, and ID attributes on components are translated in such a way that the offsets into the original MXML file are put into the ActionScript parse tree.

ASOffsetInformation can be used to take an offset into a MXML or ActionScript file and find the corresponding position in the ActionScript parse tree (as an IASNode). From there, you can walk the parse tree. Some parse tree nodes are IExpressionNodes, for which you can retrieve a definition. Depending on context, individual identifiers may have definitions that are IVariables, IFunctions, IInterfaces, IClasses, or IPackages. Composite expressions (like foo.bar or (12+16)/4) will always resolve to an IClass or IInterface. Other parse tree nodes are IScopedNodes. These represent the nested scopes in the document ({} blocks, function bodies, class bodies, package bodies, and files). You can retrieve an IASScope from an IScopedNode and use it to look up definitions that are in scope.

com.adobe.flexbuilder.search

Search provides the ability to find declarations and references for given IDefinitions across a file, project or the entire Eclipse workspace. A search performed against the ISearchIndex is composed of a SearchScope that determines where to search, a SearchFilter that determines what to return and results in the form of IOccurrences. An IOccurrence contains information about the result, such as file, start offset and end offset. An IDefinitionOccurrence provided information about a match that resolves to an IDefinition such as its containing type. An ISWCOccurrence is an occurrence found within the source of a SWC, and an ITextualOccurrence is an occurrence found within literals or comments.

com.adobe.flexbuilder.codemodel.swc

Cache of SWFs and icons from SWC files in the project.

Tips

Examples


    /**
     * Given an open Flex project, get all qualified class names (e.g. mx.core.Button) in the project.
     * @param flexProject        Flex project
     * @return                    array of qualified class names
     */
    static public String [] getAllQualifiedClassNamesInProject(IFlexProject flexProject)
    {
        // Make sure the project has been registered. It will already have been registered
        // if the user has already opened an MXML or ActionScript file in the project or any
        // of its linked folders.
        CMFactory.getRegistrar().registerProject(flexProject.getProject(), null);

        String [] allClassNames = new String[0];
        synchronized (CMFactory.getLockObject())
        {
            IProject project = CMFactory.getManager().getProjectFor(flexProject.getProject());
            if (project != null)
            {
                IClassNameIndex classIndex = (IClassNameIndex)project.getIndex(IClassNameIndex.ID);
                if (classIndex != null)
                {
                    IClass [] allClasses = classIndex.getAllClasses();
                    allClassNames = new String[allClasses.length];
                    for (int i = 0; i < allClasses.length; i++)
                    {
                        allClassNames[i] = allClasses[i].getQualifiedName();
                    }
                }
            }
        }
        return allClassNames;
    }
    
    /**
     * Given an open Flex project and a component, find the default property for that component (which is
     * defined with a [DefaultProperty("")] metadata attribute above the class that generates the component)
     * @param flexProject        Flex project
     * @param componentName        full name of the component (XML namespace + short name)
     * @return                    name of the default property
     */
    static public String getDefaultPropertyForComponent(IFlexProject flexProject, XMLName componentName)
    {
        // Make sure the project has been registered. It will already have been registered
        // if the user has already opened an MXML or ActionScript file in the project or any
        // of its linked folders.
        CMFactory.getRegistrar().registerProject(flexProject.getProject(), null);

        String defaultPropertyName = null;
        synchronized (CMFactory.getLockObject())
        {
            IProject project = CMFactory.getManager().getProjectFor(flexProject.getProject());
            if (project != null)
            {
                ITagInformationIndex tagIndex = (ITagInformationIndex)project.getIndex(ITagInformationIndex.ID);
                if (tagIndex != null)
                {
                    ITagInformation tagInfo = tagIndex.getTagInformation(componentName);
                    if (tagInfo != null)
                    {
                        IClass currentClass = tagInfo.getClassForTag();
                        HashSet recursionGuard = new HashSet();
                        while (currentClass != null)
                        {
                            IMetaTags tags = currentClass.getMetaTags();
                            if (tags != null)
                            {
                                IMetaTag defaultTag = tags.getTagByName("DefaultProperty"); //$NON-NLS-1$
                                if (defaultTag instanceof IDefaultPropertyTag)
                                {
                                    defaultPropertyName = ((IDefaultProperty)defaultTag.getPropertyName();
                                    break;
                             }
                            }
                            currentClass = currentClass.getBaseClassDefinition(recursionGuard);
                        }
                    }
                }
            }
        }
        return defaultPropertyName;
    }
    
    /**
     * Given an open Flex project, a component, and a property name, find the variable that corresponds to the
     * component property and get the fully qualified name of its type (e.g. "Array" or "mx.controls.Button").
     * @param flexProject            Flex project
     * @param componentName            full name of the component (XML namespace + short name)
     * @param propertyName            name of a component property
     * @return                        fully qualified name of the type of the component property
     */
    static public String getTypeOfComponentProperty(IFlexProject flexProject, XMLName componentName, String propertyName)
    {    
        // Make sure the project has been registered. It will already have been registered
        // if the user has already opened an MXML or ActionScript file in the project or any
        // of its linked folders.
        CMFactory.getRegistrar().registerProject(flexProject.getProject(), null);

        String defaultPropertyName = null;
        synchronized (CMFactory.getLockObject())
        {
            IProject project = CMFactory.getManager().getProjectFor(flexProject.getProject());
            if (project != null)
            {
                ITagInformationIndex tagIndex = (ITagInformationIndex)project.getIndex(ITagInformationIndex.ID);
                if (tagIndex != null)
                {
                    ITagInformation tagInfo = tagIndex.getTagInformation(componentName);
                    if (tagInfo != null)
                    {
                        ITagAttribute attributeInfo = tagInfo.getTagAttribute(propertyName);
                        if (attributeInfo instanceof ITagInspectableAttribute)
                        {
                            IVariable inspectableVariable = ((ITagInspectableAttribute)attributeInfo).getInspectable();
                            if (inspectableVariable != null)
                            {
                                IDefinition variableType = inspectableVariable.resolveVariableType(new ASDefinitionCache());
                                defaultPropertyName = variableType != null ? variableType.getQualifiedName() : null;
                            }
                        }
                    }
                }
            }
        }
        return defaultPropertyName;
    }
    
    /**
     * Given a document and an offset, build an array of all of the classes, interfaces, functions, and variables
     * in scope at the particular offset.
     * @param document                open document
     * @param offset                offset into document
     * @return                        array of definitions in scope
     */
    static public String [] getAllDefinitionsInScope(IDocument document, int offset)
    {
        String [] definitionStrings = new String[0];
        synchronized (CMFactory.getLockObject())
        {
            IProject project = CMFactory.getManager().getProjectForDocument(document);
            if (project != null)
            {
                IPath documentPath = CMFactory.getManager().getPathForDocument(document);
                IFileNode fileNode = project.findFileNodeInProject(documentPath);
                ASOffsetInformation offsetInformation = new ASOffsetInformation(offset, fileNode);

                IASNode immediateNode = offsetInformation.getContainingNode();
                IASNode currentNode = immediateNode;
                while (currentNode != null && !(currentNode instanceof IScopedNode))
                    currentNode = currentNode.getParent();
                if (currentNode instanceof IScopedNode)
                {
                    IASScope scope = ((IScopedNode)currentNode).getScope();
                    ASDefinitionFilter filter = ASDefinitionFilter.createAllSymbolsFilter(immediateNode);

                    ArrayList definitionList = new ArrayList();
                    scope.findAllDefinitions(filter, new ASDefinitionCache(), definitionList);
                    ArrayList stringList = new ArrayList();
                    Iterator definitions = definitionList.iterator();
                    while (definitions.hasNext())
                    {
                        IDefinition currentDefinition = (IDefinition)definitions.next();
                        if (!currentDefinition.isImplicit())
                        {
                            if (currentDefinition instanceof IVariable ||
                                    currentDefinition instanceof IClass ||
                                    currentDefinition instanceof IInterface)
                            {
                                // Getters and setters implement both IVariable and IFunction. By looking for
                                // IVariable first, we're treating them as variables for our list.
                                stringList.add(currentDefinition.getName());
                            }
                            else if (currentDefinition instanceof IFunction)
                            {
                                IFunction currentFunction = (IFunction)currentDefinition;
                                if (!currentFunction.isConstructor())
                                {
                                    String functionString = currentFunction.getName();
                                    functionString += "("; //$NON-NLS-1$
                                    IVariable [] arguments = currentFunction.getArguments();
                                    for (int i = 0; i < arguments.length; i++)
                                    {
                                        if (i > 0)
                                            functionString += ","; //$NON-NLS-1$
                                        functionString += arguments[i].getName();
                                    }
                                    functionString += ")"; //$NON-NLS-1$
                                    stringList.add(functionString);
                                }
                            }
                        }
                    }
                    
                    definitionStrings = (String [])stringList.toArray(new String[0]);
                }
            }
        }
        return definitionStrings;
    }