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

Доработано:
- Реализован опциональный режим (управляется параметром #SaveGoBackPosition) сохранения в кэше исходной позиции курсора для возможности возврата с помощью скрипта AXGoBack (AXGoBack - скрипт для возврата к предыдущей позиции курсора в редакторе). Значение по умолчанию: Включен.

Исправлено:
- AX 3: Добавлена очистка кэша параметров после выполнения отложенного вызова функции перехода к объявлению переменной в AX 3.

X++:
//AXGoToDeclarationXRef ver. 1.0.3 beta (for AX 3, AX 4, AX 2009), 13.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; Default = 0
    #define.SaveGoBackPosition(1) //1 - Save current cursor position in the Infolog's cache for using in AXGoBack script; 0 - Othewise; Default = 1
    //<< 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')
    #define.GoBackParamsCache('AXGoBackParams')

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

    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);

        if (treeNode)
        {
            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 (#SaveGoBackPosition)
                    {
                        infolog.globalCache().set(#GoBackParamsCache, #GoBackParamsCache, [methodNodePath, editorLine, editorColumn]);
                    }

                    #if.AX4OrAX5
                        treeNode.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);
                globalCache.clear(#ParamsCache);
            }
            return;
        }
    #endif

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

    curDeclMethodNodePath = methodNodePath;

    //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; 13.06.2010 в 15:56.
За это сообщение автора поблагодарили: Ansi (0), Pustik (5).