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