ver. 1.0.1 beta, 07.06.2010
Доработано:
- Реализована обработка некорректных вызовов для случая, когда в области курсора не найдена переменная. Добавлен вывод информационного сообщения.
- Добавлен опциональный режим вывода в Infolog иерархии классов, если объявление переменной найдено в родительском классе. Значение по умолчанию: Выключен.
- Убран addIns_ из названия, поскольку, как мне кажется, для такого скрипта процесс вызова из еще одного подменю слишком долгий.
Исправлено:
- Исправлена ошибка, возникавшая при поиске в родительских классах.
X++:
//AXGoToDeclarationXRef ver. 1.0.1 beta (for AX 3, AX 4, AX 2009), 07.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;
#endif
#define.ClassDeclMethodPath('\\classDeclaration')
#define.MethodsNodePath('\\Methods')
#define.ClassHierarchyDivider(' -> ')
#define.ClassHierarchyLabel('Classes: ')
#define.NothingIsFoundMessage('Nothing is found.')
#define.IncorrectCallMessage('Incorrect call.')
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);
}
TreeNode::findNode(_treeNodePath).AOTedit(tmpXRefDeclaration.line, tmpXRefDeclaration.Column);
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 found
classHierarchy += #ClassHierarchyDivider + tmpXRefDeclaration.ParentName;
curDeclMethodNodePath = #ClassesPath + '\\' + tmpXRefDeclaration.ParentName + #ClassDeclMethodPath;
if (searchForDeclaration(curDeclMethodNodePath))
{
return true;
}
else
{
return checkParentClassesDeclMethods(curDeclMethodNodePath);
}
}
else
{
return false;
}
}
;
//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;
}