Показать сообщение отдельно
Старый 09.06.2010, 02:12   #4  
alex55 is offline
alex55
MCTS
MCBMSS
 
224 / 145 (5) +++++
Регистрация: 13.02.2007
Адрес: Москва
ver. 1.0.2 beta, 08.06.2010

Исправлено:
- Реализован отложенный вызов функции перехода к объявлению переменной в AX 3 для исправления ситуации с потерей фокуса и невидимостью символа курсора после перехода на уже открытые окна (актуально только для AX 3).

Примечание:
- Для установки данной версии на AX 3 при изменении названия утилиты в EditorScripts необходимо изменить его также в вызове функции methodstr(EditorScripts, aaAXGoToDeclarationXRef) в коде, иначе компиляция не будет выполнена успешно.

X++:
//AXGoToDeclarationXRef ver. 1.0.2 beta (for AX 3, AX 4, AX 2009), 08.06.2010
//Developed by alex55 (AXforum.info), 06.06.2010
//Home page: axforum.info/forums/showthread.php?t=33344
//Thanks to kashperuk, miklenew and Alex_KD from AXForum.info for some used ideas
void aaAXGoToDeclarationXRef(Editor e)
{
    //Parameters section >>
    #define.PrintClassHierarchy(0) //1 - Print current class hierarchy in the infolog during search; 0 - Othewise
    //<< Parameters section

    #AOT

    #if.ReferencesPath
        #define.AX4OrAX5
    #endif

    #if.AX4OrAX5
        xRefTmpReferences   tmpXRefUse;
    #endif

    #ifnot.AX4OrAX5
        TmpxRefReferences   tmpXRefUse;
        SysGlobalCache      globalCache;
    #endif

    #define.ClassDeclMethodPath('\\classDeclaration')
    #define.MethodsNodePath('\\Methods')
    #define.ClassHierarchyDivider(' -> ')
    #define.ClassHierarchyLabel('Classes: ')
    #define.NothingIsFoundMessage('Nothing is found.')
    #define.IncorrectCallMessage('Incorrect call.')
    #define.ThisClassCache('AXGoToDeclarationXRefClass')
    #define.ParamsCache('AXGoToDeclarationXRefParams')

    TreeNode            treeNode;
    TreeNodePath        curDeclMethodNodePath; //Path of current declaration method candidate
    Column              editorColumn;
    Line                editorLine;
    xRefName            xRefName;
    TreeNodeName        rootNodeName;

    str                 classHierarchy;

    str getElementNameFromPath(TreeNodePath     _treeNodePath)
    {
        int secondBackSlashPos;
        int thirdBackSlashPos;
        ;
        secondBackSlashPos = strfind(_treeNodePath, '\\', 2, strlen(_treeNodePath) - 1);
        thirdBackSlashPos = strfind(_treeNodePath, '\\', secondBackSlashPos + 1, strlen(_treeNodePath) - secondBackSlashPos);

        return substr(_treeNodePath, secondBackSlashPos + 1, thirdBackSlashPos - secondBackSlashPos - 1);
    }

    boolean searchForDeclaration(
        TreeNodePath        _treeNodePath
    )
    {
        #if.AX4OrAX5
            xRefTmpReferences   tmpXRefDeclaration;
        #endif

        #ifnot.AX4OrAX5
             TmpxRefReferences   tmpXRefDeclaration;
        #endif
        ;

        treeNode = TreeNode::findNode(_treeNodePath);
        treeNode.AOTmakeXref(1);

        if (!tmpXRefUse)
        {
            //The tmpXRefUse is init only one time (only for original method node path)
            tmpXRefUse = xRefCreate::makeTmp(infolog.lastxRef());
            select firstonly tmpXRefUse
            order by Column desc
            where
                tmpXRefUse.line == editorLine
                && tmpXRefUse.Column <= editorColumn
            ;

            if (tmpXRefUse)
            {
                xRefName = tmpXRefUse.name;
            }
        }

        if (xRefName)
        {
            tmpXRefDeclaration = xRefCreate::makeTmp(infolog.lastxRef());

            select firstonly tmpXRefDeclaration
            where
                tmpXRefDeclaration.Reference == XRefReference::Declaration
                && tmpXRefDeclaration.name == xRefName;

            if (tmpXRefDeclaration)
            {
                if (classHierarchy && #PrintClassHierarchy)
                {
                    info(classHierarchy);
                }

                if (treeNode)
                {
                    #if.AX4OrAX5
                         TreeNode::findNode(_treeNodePath).AOTedit(tmpXRefDeclaration.line, tmpXRefDeclaration.Column);
                    #endif

                    #ifnot.AX4OrAX5
                        infolog.globalCache().set(#ThisClassCache, #ThisClassCache, this);
                        infolog.globalCache().set(#ParamsCache, #ParamsCache, [_treeNodePath, tmpXRefDeclaration.line, tmpXRefDeclaration.Column]);
                        infolog.addTimeOut(this, methodstr(EditorScripts, aaAXGoToDeclarationXRef), 10, false);
                    #endif
                }

                return true;
            }
        }

        return false;
    }

    boolean checkParentClassesDeclMethods(TreeNodePath _curClassDeclMethodNodePath)
    {
        #if.AX4OrAX5
            xRefTmpReferences   tmpXRefDeclaration;
        #endif

        #ifnot.AX4OrAX5
            TmpxRefReferences   tmpXRefDeclaration;
        #endif
        ;

        if (!classHierarchy)
        {
            classHierarchy = #ClassHierarchyLabel + getElementNameFromPath(_curClassDeclMethodNodePath);
        }

        treeNode = TreeNode::findNode(_curClassDeclMethodNodePath);
        treeNode.AOTmakeXref(1);
        tmpXRefDeclaration = xRefCreate::makeTmp(infolog.lastxRef());

        select firstonly tmpXRefDeclaration
        where
            tmpXRefDeclaration.Kind == xRefKind::Class
            && tmpXRefDeclaration.Reference == XRefReference::Definition
            && tmpXRefDeclaration.ParentName
        ;

        if (tmpXRefDeclaration)
        {
            //Parent class was found
            classHierarchy += #ClassHierarchyDivider + tmpXRefDeclaration.ParentName;

            curDeclMethodNodePath = #ClassesPath + '\\' + tmpXRefDeclaration.ParentName + #ClassDeclMethodPath;

            if (searchForDeclaration(curDeclMethodNodePath))
            {
                return true;
            }
            else
            {
                return checkParentClassesDeclMethods(curDeclMethodNodePath);
            }
        }
        else
        {
            return false;
        }
    }
    ;

    #ifnot.AX4OrAX5
        //Asynchronous call of AOTedit method for AX 3 (solution of the lost focus issue)
        if (!e)
        {
            globalCache = infolog.globalCache();
            if (globalCache)
            {
                [curDeclMethodNodePath, editorLine, editorColumn] = globalCache.get(#ParamsCache, #ParamsCache, conNull());
                TreeNode::findNode(curDeclMethodNodePath).AOTedit(editorLine, editorColumn);
                globalCache.clear(#ThisClassCache);
            }
            return;
        }
    #endif

    //Init
    editorLine = e.currentLineNo() + 1;
    editorColumn = e.ColumnNo() + 1;
    curDeclMethodNodePath = e.path();

    //Search in declaration block of the method itself
    if (searchForDeclaration(curDeclMethodNodePath))
    {
        return;
    }
    else
    {
        if (!xRefName)
        {
            //Incorrect call
            info(#IncorrectCallMessage);
            return;
        }
    }

    if (strscan(curDeclMethodNodePath, #ClassesPath, 1, strlen(curDeclMethodNodePath)))
        rootNodeName = #ClassesPath;
    else
        if (strscan(curDeclMethodNodePath, #FormsPath, 1, strlen(curDeclMethodNodePath)))
            rootNodeName = #FormsPath;
        else
            if (strscan(curDeclMethodNodePath, #ReportsPath, 1, strlen(curDeclMethodNodePath)))
                rootNodeName = #ReportsPath;

    if (rootNodeName)
    {
        //Search in classDeclaration method of the current class/form/report
        switch (rootNodeName)
        {
            case #ClassesPath:
                treeNode = treeNode.AOTparent();
                curDeclMethodNodePath =  treeNode.treeNodePath() + #ClassDeclMethodPath;
                break;
            case #FormsPath:
            case #ReportsPath:
                while (treeNode.treeNodePath() != rootNodeName
                )
                {
                    curDeclMethodNodePath = treeNode.treeNodePath();
                    treeNode = treeNode.AOTparent();
                }

                curDeclMethodNodePath += #MethodsNodePath + #ClassDeclMethodPath;
                break;
        }

        if (searchForDeclaration(curDeclMethodNodePath))
        {
            return;
        }
    }

    if (strscan(curDeclMethodNodePath, #ClassesPath, 1, strlen(curDeclMethodNodePath)))
    {
        //Search in classDeclaration method of all parents of the current class
        if (checkParentClassesDeclMethods(curDeclMethodNodePath))
        {
            return;
        }
    }

    info(#NothingIsFoundMessage);

    return;
}

Последний раз редактировалось alex55; 09.06.2010 в 02:38.