Probleme : savoir l'objet appellant methode
yassirjanati
Messages postés
36
Statut
Membre
-
yassirjanati Messages postés 36 Statut Membre -
yassirjanati Messages postés 36 Statut Membre -
Bonjour,
je suis en train de generer un graphe des appels des methodes d'un projet eclipse.
je vais essayer d'explique mon exemple par exemple :
class A {public void m1(){m2();}
public void m2(){}}
class B extends A{public void m2(){}}
maintenant dans une methde main qu'on je veux appler m1() de B
void main() {
new B().m1();
}
quand je fais calleeHierarchy de main
je trouve A.m1()
et comme ca je vais perdre le chemin correcte car aprés si je ferai calleeHierarchy de m1() je trouverai A.m2()
mais en realité je devrai avoir B.m1() et B.m2()
donc le probleme c'est j'arrive pas a savoir l'objet de class qui appelle m1() si instance de A ou de B
Merci
je suis en train de generer un graphe des appels des methodes d'un projet eclipse.
je vais essayer d'explique mon exemple par exemple :
class A {public void m1(){m2();}
public void m2(){}}
class B extends A{public void m2(){}}
maintenant dans une methde main qu'on je veux appler m1() de B
void main() {
new B().m1();
}
quand je fais calleeHierarchy de main
je trouve A.m1()
et comme ca je vais perdre le chemin correcte car aprés si je ferai calleeHierarchy de m1() je trouverai A.m2()
mais en realité je devrai avoir B.m1() et B.m2()
donc le probleme c'est j'arrive pas a savoir l'objet de class qui appelle m1() si instance de A ou de B
Merci
14 réponses
Je ne vois pas d'autre solution que de tester si ton objet est une instance de telle ou telle classe, (avec le mot-clé
instanceof) par exemple :
if (objet instanceof B){
//modifier ton chemin en remplaçant A par B pour retourner le bon chemin
}
Mais le probleme que j'ai c'est j'arrive pas a detecter le nom de l'objet car le resultat qui me donne de call hierarchy c'est toujours de A et jamais pour B, alors je n'ai pas trouvé comment savoir cet objet.
Si l'objet déclaré est la classe englobante (classe abstraite ou interface) call hierarchy te retournera toujours cette classe englobante et non la classe instanciée (celle que tu cherches). Il te faudra forcément tester "en dur" avec instanceof si l'objet retourné provient de telle ou telle classe que tu devras toi-même lister. Je ne sais pas si ca pourra t'aider d'une quelconque façon mais tu peux aussi utiliser Type hierarchy (sous eclipse puisque je suppose que c'est la dessus que tu travailles ou un éditeur similaire) pour naviguer entre les interfaces, les classes abstraites et celles étendues qui en dépendent.
Si c'est pour avoir juste le nom de la classe, tu peux par exemple ajouter une méthode dans ton interface A :
De cette façon, à partir de l'objet que tu récupère par call hierarchy, tu peux récupérer le nom de la classe instanciée.
Si rien de ca ne te satisfait et que tu penses que j'ai mal compris le problème, précises ton problème avec des parties plus précises de code notamment.
Si c'est pour avoir juste le nom de la classe, tu peux par exemple ajouter une méthode dans ton interface A :
String getNomClasse();et la déclarer dans la classe concrète B :
String getNomClasse() {
return "B";
}
De cette façon, à partir de l'objet que tu récupère par call hierarchy, tu peux récupérer le nom de la classe instanciée.
Si rien de ca ne te satisfait et que tu penses que j'ai mal compris le problème, précises ton problème avec des parties plus précises de code notamment.
Bon le code source du projet cible contient plus de 8000 classes et j'ai pas le droit de le modifier car c'est pour un grand projet,
vous avez ecrit "Il te faudra forcément tester "en dur" avec instanceof si l'objet retourné provient de telle ou telle classe" c'est quoi l'objet retourné ??
je reexplique un peu
class A {
public void m1(){m2();}
public void m2(){ X.mx()}}
class B extends A{
public void m2(){Y.my()}}
class X{
public void mx(){}}
class Y{
public void my(){}}
on a maintenant
main()
{
new B().m1();
new A().m1();
}
le resultat qu'on doit avoir :::
--> A.m1() ----> B.m2() -----> Y.my()
main |
--> A.m1() ----> A.m2() -----> X.mx()
mais le resultat que je trouve toujours pour ts les cas c'est
main() --> A.m1() ----> X.m2() -----> X.mx()
car pour calleeHierarchy de new B().m1(); et de new A().m1(); donne m1 de A et et automatiquement aprés calleeHierarchy de m1(); donne m2 de A.
donc le probleme c'est je trouve pas comment savoir que m1 est appelée par Y pour faire le traitement pour changer le sens du chemin ds le graphe.
par exemple si j'arrive a connaitre que m1() est appelée par B je peux verifier si m2 est surchargé sur B ou pas, si je la trouve j'ajoute celle de B sinn j'ajoute celle de A.
mais comment savoir que m1() est appelée de B et pas de A dans ce cas new B().m1();
vous avez ecrit "Il te faudra forcément tester "en dur" avec instanceof si l'objet retourné provient de telle ou telle classe" c'est quoi l'objet retourné ??
je reexplique un peu
class A {
public void m1(){m2();}
public void m2(){ X.mx()}}
class B extends A{
public void m2(){Y.my()}}
class X{
public void mx(){}}
class Y{
public void my(){}}
on a maintenant
main()
{
new B().m1();
new A().m1();
}
le resultat qu'on doit avoir :::
--> A.m1() ----> B.m2() -----> Y.my()
main |
--> A.m1() ----> A.m2() -----> X.mx()
mais le resultat que je trouve toujours pour ts les cas c'est
main() --> A.m1() ----> X.m2() -----> X.mx()
car pour calleeHierarchy de new B().m1(); et de new A().m1(); donne m1 de A et et automatiquement aprés calleeHierarchy de m1(); donne m2 de A.
donc le probleme c'est je trouve pas comment savoir que m1 est appelée par Y pour faire le traitement pour changer le sens du chemin ds le graphe.
par exemple si j'arrive a connaitre que m1() est appelée par B je peux verifier si m2 est surchargé sur B ou pas, si je la trouve j'ajoute celle de B sinn j'ajoute celle de A.
mais comment savoir que m1() est appelée de B et pas de A dans ce cas new B().m1();
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Quelle est la methode calleeHierarchy dont tu parles?
S'agit il d'une fonction de eclipse par laquelle tu ouvres la vue Call hierarchy, ou bien une methode existante ou présente dans ton code?
Comment obtiens tu ce resultat ?
main() --> A.m1() ----> X.m2() -----> X.mx()
Comment peux tu obtenir X.m2() en deuxieme alors qu'il n'y a pas de méthode m2() dans X ?
Lorsque tu utilises la méthode qui te permet de savoir l'appelant sur A.m1(), j'imagines que tu obtiens un objet, en l'occurence c'est sur cet objet que tu dois faire tes test instanceof pour savoir de quelle classe instanciée ils proviennent.
S'agit il d'une fonction de eclipse par laquelle tu ouvres la vue Call hierarchy, ou bien une methode existante ou présente dans ton code?
Comment obtiens tu ce resultat ?
main() --> A.m1() ----> X.m2() -----> X.mx()
Comment peux tu obtenir X.m2() en deuxieme alors qu'il n'y a pas de méthode m2() dans X ?
Lorsque tu utilises la méthode qui te permet de savoir l'appelant sur A.m1(), j'imagines que tu obtiens un objet, en l'occurence c'est sur cet objet que tu dois faire tes test instanceof pour savoir de quelle classe instanciée ils proviennent.
Bonjour,
d'abord pour callHierarchy est d'eclipse mais je choisis si appelant ou appelé.
pour X.m2() c'est A.m2() juste erreur d'ecriture.
Lorsque j'utilise la méthode qui me permet de savoir l'appelant sur A.m1(), je trouve la methode et appelante et la classe ou elle est definie et aucune information sur l'objet.
Alors j'explique plus ::
par exemple on plus que les classes ci dessus
class I{
public void mi(){
new B().m1(); }}
class H{
public void mh(){
new A().m1(); }}
- Alors si on utilise callHierarchy avec callee sur mi() et mh() comme racine du graphe ::
on trouve après les callHierarchy :::
I.mi() --> A.m1() ----> A.m2() -----> X.mx()
H.mh() --> A.m1() ----> A.m2() -----> X.mx()
ce resultat est faux.
- Alors si on utilise callHierarchy avec caller sur mi() et et mh() comme racine du graphe ::
on trouve après les callHierarchy :::
I.mi() ---| -> B.m2() -----> Y.my()
-> A.m1()
H.mh() -| -> A.m2() -----> X.mx()
Alors aussi graphe incomplet parce que quand on veux parcourir et on veut chercher par exemple le chemin des appels de I.mi() on arrive a A.m&() et on perd le sens si de B.m2() ou de A.m2() .
d'abord pour callHierarchy est d'eclipse mais je choisis si appelant ou appelé.
pour X.m2() c'est A.m2() juste erreur d'ecriture.
Lorsque j'utilise la méthode qui me permet de savoir l'appelant sur A.m1(), je trouve la methode et appelante et la classe ou elle est definie et aucune information sur l'objet.
Alors j'explique plus ::
par exemple on plus que les classes ci dessus
class I{
public void mi(){
new B().m1(); }}
class H{
public void mh(){
new A().m1(); }}
- Alors si on utilise callHierarchy avec callee sur mi() et mh() comme racine du graphe ::
on trouve après les callHierarchy :::
I.mi() --> A.m1() ----> A.m2() -----> X.mx()
H.mh() --> A.m1() ----> A.m2() -----> X.mx()
ce resultat est faux.
- Alors si on utilise callHierarchy avec caller sur mi() et et mh() comme racine du graphe ::
on trouve après les callHierarchy :::
I.mi() ---| -> B.m2() -----> Y.my()
-> A.m1()
H.mh() -| -> A.m2() -----> X.mx()
Alors aussi graphe incomplet parce que quand on veux parcourir et on veut chercher par exemple le chemin des appels de I.mi() on arrive a A.m&() et on perd le sens si de B.m2() ou de A.m2() .
Je vais essayer de résumer pour voir si j'ai mieux compris et clarifier les choses :
Bon deja on parle du graphe des appelés. c'est celui là que tu obtiens. le graphe des appelants serait obtenus en partant de X.mx() ou de Y.my(), et en leur demandant qui les a appelés et en remontant ainsi on arriverait jusqu'au main().
Ensuite le problème se situe ici :
lorsque tu demandes quel appel est fait par I.mi(), tu obtiens A.m1() alors que tu devrais obtenir B.m1().
La raison pour laquelle tu obtiens A.m1() a la place de B.m1() est que B hérite de A et que l'appel a callHierarchy te renvoie obligatoirement la classe englobante.
Si je comprends bien c'est ici que se situe le problème de fond. C'est directement la façon dont tu récupères l'information sur quelle classe est appelée par I.mi() qui pose le problème, elle récupère la classe la plus haute au lieu de la classe héritée si c'est le cas.
Il faut regarder du côté de ta méthode/fonction/autre qui fait callHierarchy pour voir exactement pourquoi tu récupères la mauvaise classe.
J'ai cru comprendre maintenant que ce que tu utilises, ce n'est pas la "vue call hierarchy" que tu peux obtenir en faisant "click droit" sur une méthode/Classe/autre et en cliquant sur "Open Call Hierachy", c'est plutot une Classe Java qui ressemble ou utilise quelque chose comme ca (j'ai trouvé ca sur le net)
http://www.docjar.com/docs/api/org/eclipse/jdt/internal/corext/callhierarchy/CallHierarchy.html
Et donc c'est cette précisément cette classe/methode que tu dois regarder, modifier, ou au moins montrer ici pour pouvoir voir s'il ya une solution.
Pour tout le message, corriges moi si je me trompe, ca m'aidera a comprendre mieux (pas que pour moi d'ailleurs)
Bon deja on parle du graphe des appelés. c'est celui là que tu obtiens. le graphe des appelants serait obtenus en partant de X.mx() ou de Y.my(), et en leur demandant qui les a appelés et en remontant ainsi on arriverait jusqu'au main().
Ensuite le problème se situe ici :
lorsque tu demandes quel appel est fait par I.mi(), tu obtiens A.m1() alors que tu devrais obtenir B.m1().
La raison pour laquelle tu obtiens A.m1() a la place de B.m1() est que B hérite de A et que l'appel a callHierarchy te renvoie obligatoirement la classe englobante.
Si je comprends bien c'est ici que se situe le problème de fond. C'est directement la façon dont tu récupères l'information sur quelle classe est appelée par I.mi() qui pose le problème, elle récupère la classe la plus haute au lieu de la classe héritée si c'est le cas.
Il faut regarder du côté de ta méthode/fonction/autre qui fait callHierarchy pour voir exactement pourquoi tu récupères la mauvaise classe.
J'ai cru comprendre maintenant que ce que tu utilises, ce n'est pas la "vue call hierarchy" que tu peux obtenir en faisant "click droit" sur une méthode/Classe/autre et en cliquant sur "Open Call Hierachy", c'est plutot une Classe Java qui ressemble ou utilise quelque chose comme ca (j'ai trouvé ca sur le net)
http://www.docjar.com/docs/api/org/eclipse/jdt/internal/corext/callhierarchy/CallHierarchy.html
Et donc c'est cette précisément cette classe/methode que tu dois regarder, modifier, ou au moins montrer ici pour pouvoir voir s'il ya une solution.
Pour tout le message, corriges moi si je me trompe, ca m'aidera a comprendre mieux (pas que pour moi d'ailleurs)
Oui, vous avez bien compris mon probleme (100%).
j'ai essayé de chercher dans les methodes de cette class mais je trouve rien qui m'aide.
j'ai essayé de chercher dans les methodes de cette class mais je trouve rien qui m'aide.
Si tu peux, peux tu copier ici la partie du code qui fait l'appel à CallHierarchy sur l'objet I.mi() pour obtenir A.m1() et SURTOUT la méthode en question de la classe CallHierarchy ?
(Ou bien un exemple d'appel sur une de tes 8000 classe, peu importe, c'est pour avoir un exemple de la façon dont tu récupères les classes appelées)
(Ou bien un exemple d'appel sur une de tes 8000 classe, peu importe, c'est pour avoir un exemple de la façon dont tu récupères les classes appelées)
Voila la methode que j'utilise pour recuperer les methodes appelées ::
public static List<IMethod> getCalleeHierarchy(IMethod method){
List<IMethod> methodsCalls= new ArrayList<IMethod>();
MethodWrapper[] methodWrappers= CallHierarchy.getDefault().getCalleeRoots(new IMethod[] {method});
MethodWrapper wrapper=methodWrappers[0];
MethodWrapper[] calls= wrapper.getCalls(new NullProgressMonitor());
for (MethodWrapper call:calls){
IMethod callMethod=null;
if (call.getMember() instanceof IMethod) {
callMethod= (IMethod) call.getMember();
methodsCalls.add(callMethod);
}
}
/// cette methode juste pour filtrer les methodes du projets
methodsCalls= filtrerPackage(methodsCalls, BASE_PACKAGE);
return methodsCalls;
}
public static List<IMethod> getCalleeHierarchy(IMethod method){
List<IMethod> methodsCalls= new ArrayList<IMethod>();
MethodWrapper[] methodWrappers= CallHierarchy.getDefault().getCalleeRoots(new IMethod[] {method});
MethodWrapper wrapper=methodWrappers[0];
MethodWrapper[] calls= wrapper.getCalls(new NullProgressMonitor());
for (MethodWrapper call:calls){
IMethod callMethod=null;
if (call.getMember() instanceof IMethod) {
callMethod= (IMethod) call.getMember();
methodsCalls.add(callMethod);
}
}
/// cette methode juste pour filtrer les methodes du projets
methodsCalls= filtrerPackage(methodsCalls, BASE_PACKAGE);
return methodsCalls;
}
La ca devient tres complique ca m'étonnerait que tu puisses passer par là pour résoudre ton problème et je ne suis donc pas sur que ca soit faisable.
A vue de nez, mais je ne sais pas réellement si ca peut aller vers une solution, mais d'après moi, il faudrait fouiller du coté de
car c'est ici que ce code semble tester l'appartenance de l'objet à telle ou telle classe, donc il faudrait regarder du côté de la classe IMethod, ce qu'elle contient, et comment les classes sont déclarées dedans, mais le mieux serait de demander aux développeurs des classes en question le fonctionnement, sinon je pense que tu n'arriveras pas a résoudre ton problème.
Personnellement je ne peux pas t'aider plus il faut rentrer dans l'ensemble des classes en question et c'est beaucoup de travail. Tu peux toujours espérer que quelqu'un d'autre sur ce forum puisse t'aider mais j'en doute. Je te conseille juste de remonter ton sujet de temps en temps au cas ou quelqu'un puisse t'aider, mais surtout si tu peux, essayes de contacter les développeurs des classes.
Bon courage
A vue de nez, mais je ne sais pas réellement si ca peut aller vers une solution, mais d'après moi, il faudrait fouiller du coté de
if (call.getMember() instanceof IMethod)
car c'est ici que ce code semble tester l'appartenance de l'objet à telle ou telle classe, donc il faudrait regarder du côté de la classe IMethod, ce qu'elle contient, et comment les classes sont déclarées dedans, mais le mieux serait de demander aux développeurs des classes en question le fonctionnement, sinon je pense que tu n'arriveras pas a résoudre ton problème.
Personnellement je ne peux pas t'aider plus il faut rentrer dans l'ensemble des classes en question et c'est beaucoup de travail. Tu peux toujours espérer que quelqu'un d'autre sur ce forum puisse t'aider mais j'en doute. Je te conseille juste de remonter ton sujet de temps en temps au cas ou quelqu'un puisse t'aider, mais surtout si tu peux, essayes de contacter les développeurs des classes.
Bon courage
Bon j'ai choisi cette cette procedure pour avoir la liste des appelées donc c'est comme ya pas d'autre solution,
pour call.getMember() ne donne rien sur l'objet appelant tte les infos sur la classe englobante.
mm si le cas on peut pas tester l'appartenance de l'objet à telle ou telle classe comme ca car on a des centaines de cas et on sait pas de prevu les noms des classes.
vous m'avez dit que le mieux serait de demander aux développeurs ??
j'epere sortir de ce probleme le plus proche car je suis bloqué plus de 10 jours.
En ts cas merci bien, et bonne journée
pour call.getMember() ne donne rien sur l'objet appelant tte les infos sur la classe englobante.
mm si le cas on peut pas tester l'appartenance de l'objet à telle ou telle classe comme ca car on a des centaines de cas et on sait pas de prevu les noms des classes.
vous m'avez dit que le mieux serait de demander aux développeurs ??
j'epere sortir de ce probleme le plus proche car je suis bloqué plus de 10 jours.
En ts cas merci bien, et bonne journée