Insertion automatique de code Java basée sur l'Arbre syntaxique

Aggrxtech 2021-11-25 17:27:33
insertion automatique code java bas

L'insertion de code est un moyen courant de tester et de localiser les problèmes,En insérant le code correspondant à l'emplacement du Code(“Pile”),Pour imprimer ou recueillir les données dont nous avons besoin.

Insertion automatique de pieux,C'est - à - dire à un endroit précis du Code,Insérer automatiquement une ou plusieurs lignes de code dont nous avons besoin.D'habitude, nous mettons des piles sur le Code compilé,L'avantage est d'éviter l'intrusion dans le code source,Dans une certaine mesure, les différents styles de Code des développeurs sont masqués.Ici.,Nous nous concentrons sur une autre façon d'insérer des pieux dans le code source,Si l'intrusion dans le Code n'est pas prise en compte,Il est donc plus intuitif d'insérer des pieux directement dans le code source,Il est plus facile de contrôler et de déboguer,Plus grande flexibilité,Et l'approche que cet article va introduire ne tient pas compte des différents styles de code.


Exigences relatives à l'insertion des pieux

C'est plus simple dans une structureJavaExemple de code,Supposons que nous ayons un suffixe nommé".java"Fichier source pour,Vous devez insérer une ligne de code au début de chaque méthode à l'intérieur pour imprimer le nom de la méthode courante,Au moment de l'exécution du Code,Pour savoir quelle méthode a été appelée,Pour tracer un diagramme d'appel pour l'ensemble du projet.Le code source dans le fichier est le suivant:
package com.ast.pkg;

public class ASTDemo {
int intData = 0;
double floatData = 0;
String strData = "";

//construction
public ASTDemo() {
this.intData = 123;
this.floatData = 3.14;
this.strData = "It's been a long time.";
}

public void setIntData(int data) {
this.intData = data;
}

public String getStrData() {
return this.strData;
}

public void methodDemo(String param1, String param2) {
if (null == param1 || null == param2) {
return;
}

if (param1.length() > param2.length()) {
strData = strData + param1;
} else {
strData = strData + param2;
}
}
}

Apparemment., On n'a pas pu mettre le pieu directement , Parce que de cette façon, même si vous pouvez localiser exactement la première ligne de chaque méthode , Toujours pas universel , Le même Code est écrit différemment , Ou ajouter une structure de code complexe , Ou une autre habitude d'écrire , Non seulement la première ligne du Code n'est pas reconnue , Même le réaménagement ,C'est très compliqué.. Ensuite, changeons d'avis et mettons les pieux .


JavaComposition du Code

Ce que nous devons explorer ici, c'est Java Comment le Code est construit , Ou un suffixe nommé ".java"Dans les documents de, Quelles déclarations et structures sont incluses . Par exemple, dans le code ci - dessus , Vous pouvez voir très intuitivement ,Il contient::
  • Nom du paquet

  • Nom de la classe

  • Trois attributs dans la classe

  • Une méthode de construction à l'intérieur d'une classe et les déclarations qu'elle contient

  • Trois méthodes communes dans la classe et les déclarations qu'elles contiennent


    Selon leur relation d'inclusion , Vous pouvez dessiner un tel arbre : 


Un niveau à partir du noeud racine contient tout le Code . Une représentation complète et claire de cette partie du Code et de la relation entre eux .

Arbre de syntaxe abstrait

Celui - ci là - haut"Arbre" C'est très intuitif , Mais cela montre aussi que le Code peut être abstrait sous forme d'arbre . Ensuite, nous dessinons l'arbre à une plus petite granularité .


      Arbre de syntaxe abstrait(AST) Est une représentation abstraite de la syntaxe source , Il représente la structure du Code sous forme d'arbre .En fait,Eclipse Le code source est déjà disponible ASTReprésentation, Pour aider les développeurs à être plus complets 、 Analyse claire de la structure et des relations du Code .
      Ce que nous allons réaliser ici, c'est l'insertion automatique de pieux , Ce qui signifie que nous devons analyser la structure du Code en temps réel , Ensuite, insérez le code préparé au bon endroit , Et assurez - vous que le Code post - pile peut être compilé 、Mise en œuvre.


JavaParser

Nous utilisonsJavaParser Pour traiter le code source , C'est un outil d'analyse de code plus général .AdoptionJavaParserAnalyse de,On va avoir un".java" Arbre syntaxique abstrait du fichier .Voir les étapes suivantes:

1)Références
      Après la création du projet ,IntroductionJavaParser,MavenOuGradleOui.:
  • Maven

<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core-serialization</artifactId>
<version>3.6.5</version>
</dependency>
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>3.6.5</version>
</dependency>
  • Gradle

implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.6.5'
implementation 'com.github.javaparser:javaparser-core:3.6.5'

Notez que la version référencée ne doit pas être inférieure à 3.6.4, Sinon, il y aura toutes sortes de problèmes difficiles .


2)AnalyseJavaCode source
      DépendanceJavaParserOutils,On a juste besoin d'entrer.".java"Flux d'entrée du fichier, Pour compléter l'analyse du code source .

String javaFilePath = "ASTDemo.java";
FileInputStream in = null;

try {
in = new FileInputStream(javaFilePath);
CompilationUnit compilationUnit = JavaParser.parse(in);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

JavaParserDansparseMéthodes, Génère un arbre de code basé sur le code source ,EtCompilationUnitType de retour.CompilationUnitClasse àcom.github.javaparser.astSous le sac., Introduction normale JavaParserOn peut l'utiliser.. En interrompant la forme du point , Regardons la composition de l'objet :


Pour les structures arborescentes , L'attribut le plus facile à comprendre est childNodeC'est,Au noeud racinecompilationUnit Il y a deux noeuds enfants sur , L'un est le nom du paquet auquel il appartient ,L'un estASTDemoCatégorie, Il y a sept autres noeuds enfants sous le noeud de classe , En plus du noeud nom de classe ,En plus6 Les noeuds représentent chacun trois variables d'attribut de classe , Une méthode de construction et trois méthodes ordinaires .
      Spécifique à une méthode ,ParmethodDemo(String, String)Par exemple,Il a5Sous - noeud:

Nom de la méthode ,Deux paramètres,Valeur de retour et corps de la méthode,Nous le savons tous., Le Code dans cette méthode est :

if (null == param1 || null == param2) {
return;
}
if (param1.length() > param2.length()) {
strData = strData + param1;
} else {
strData = strData + param2;
}

Continuez à suivre vers l'intérieur , Il y a deux sous - noeuds sous le noeud corps de la méthode , Chacun représente deux if

Et ainsi de suite., Quand vous affinez une déclaration , Encore une structure similaire , Par exemple, un énoncé d'affectation strData = strData + param1; Utilisez cette instruction comme noeud racine pour contenir deux noeuds enfants , À gauche et à droite de l'assignation :

"="En tant que“Affectation(ASSIGN)”Fonctionnement, Sauvegardé sur le noeud racine operatorDans les propriétés:

De même pour"="À droite.,Il y a deux noeudsstrDataEtparam2, Et le logo PLUSFonctionnementopratorPropriétés:


Vous pouvez voir que l'arbre de syntaxe abstrait contient toutes les informations du code source ,Dans cet arbre, Nous pouvons localiser avec précision n'importe quelle structure de code que nous devons identifier .


Traverser l'arbre de syntaxe

Rappelez - vous nos besoins : Insérer une déclaration pour imprimer le Journal à la première ligne de chaque méthode . Donc nous devons d'abord trouver “Chaque méthode”. Pour un arbre syntaxique abstrait, c'est trouver tous les noeuds de méthode , Naturellement, nous avons pensé traverser cet arbre .
      JavaParser L'outil offre un moyen de traverser cet arbre , Nous devons créer un VoidVisitorAdapterObjet, Et réaliser ce qui est à l'intérieur visit(SomeType, Object)Méthodes. Alors on peut traverser l'arbre de grammaire , Comment identifier quel noeud représente la méthode , Quel noeud représente une déclaration ou une propriété ? Capture d'écran du point d'arrêt précédent , Si vous regardez attentivement , Vous remarquerez sûrement que dans cet arbre , Différentes structures de code , Ses noeuds ont différents types ,Par exemple,:
Structure du Code Type de noeud
Variable d'attribut de classe FieldDeclaration
Méthode de construction ConstructorDeclaration
Méthode normale MethodDeclaration
Jugement de branche IfStmt
Instruction d'affectation AssignExpr
Appel de méthode MethodCallExpr

VoidVisitorAdapterDevisit La méthode est définie pour chaque type , Ce que nous devons identifier ici, c'est la méthode de construction et la méthode ordinaire ,Ainsi, la réalisationConstructorDeclarationEtMethodDeclaration Deux types suffisent .

VoidVisitorAdapter<Object> adapter = new VoidVisitorAdapter<Object>() { 
public void visit(MethodDeclaration methodDeclaration, Object obj) {
......
}
public void visit(ConstructureDeclaration methodDeclaration, Object obj) {
......
}
};

visit La méthode est la logique de traitement lorsqu'un noeud de type correspondant est rencontré . Il faut donc qu'on y mette des pieux .

Le Code actuel est une structure arborescente , Pour ajouter une ligne de code , Nous devons créer un noeud . Pour être aussi simple que possible , Nous insérons juste une simple instruction d'exécution System.out.println(...), Le type de déclaration est ExpressionStmt, Donc nous commençons par créer un noeud :
String pileContent = "System.out.println(...)";
ExpressionStmt expressionStmt = new ExpressionStmt();
expressionStmt.setExpression(pileContent);

Et puis..., On va mettre ce noeud au bon endroit , L'exigence est la première ligne de chaque Code de méthode , Convertir en Arbre syntaxique, c'est - à - dire ajouter ce noeud avant le premier enfant du noeud corps de la méthode :

methodDeclaration.getBody().get().getStatements().add(0, expressionStmt);

Ce qui est particulièrement important ici, c'est que, Si c'est la méthode de construction de la Sous - classe ,Parce que l'appel
super() À la première ligne , On peut donc juger si la première ligne de la méthode de construction est superMéthodes, Alors ce noeud doit être inséré dans la deuxième position ,Sinon, une erreur sera signalée lors de la compilation.
On peut appeleradapterDevisitMéthodes, Objet d'arbre syntaxique généré avant de passer ,Commencez à traverser:

adapter.visit(compilationUnit, null);

Après avoir traversé , Le Code par défaut est inséré sous chaque noeud de méthode .
Enfin,AppelezCompilationUnitDetoString() La méthode transforme l'arbre de code en source , Imprimé au même endroit ".java"Dans le document, Et écraser les données originales , Achèvement de l'insertion automatique des pieux .


版权声明
本文为[Aggrxtech]所创,转载请带上原文链接,感谢
https://javamana.com/2021/11/20211125172432416v.html

  1. JavaScript高级程序设计读后感(一)之零碎知识点查漏补缺
  2. 先到先学!Alibaba甩出第四次更新的JDK源码高级笔记(终极版)
  3. Java File类
  4. How To Install MariaDB on linux
  5. #yyds干货盘点# Mybatis 的 XML 配置
  6. Spring认证中国教育管理中心-Spring Data MongoDB教程七
  7. Linux进程和任务管理
  8. Linux文件系统日志分析
  9. Redis-客户端-重点知识
  10. Redis-事件-重点知识
  11. Redis-AOF持久化-重点知识
  12. Redis-RDB持久化-重点知识
  13. http://lx.gongxuanwang.com/sszt/32.htm
  14. 回顾我两个月面试阿里,携程,小红书,美团,网易等等(Java岗)
  15. JavaScript高级程序设计读后感(一)之零碎知识点查漏补缺
  16. Rocketmq source code analysis: message sending process
  17. Rocketmq source code analysis: how does rocketmq store messages?
  18. RocketMQ source analysis: how to debug the RocketMQ source in IDEA
  19. How To Install MariaDB on linux
  20. Comment installer mariadb sur Linux
  21. http://lx.gongxuanwang.com/sszt/7.htm
  22. Classe de fichiers Java
  23. Premier arrivé, premier servi! Alibaba lance la quatrième mise à jour de JDK source Advanced notes (Ultimate)
  24. #yyds干货盘点#设计模式之【工厂模式】
  25. Java * SpringBoot实现万能文件在线预览,已开源,真香
  26. Redis | 第4章 Redis中的数据库《Redis设计与实现》
  27. Liang Tingwei's first variety show of "director, please give advice" reshapes the classic work "spring of a new town"
  28. Redis | 第4章 Redis中的数据库《Redis设计与实现》
  29. 关于centos docker版本过低导致 is not a valid repository/tag: invalid reference format
  30. Redis 源码简洁剖析 02 - SDS 字符串
  31. 回顧我兩個月面試阿裏,攜程,小紅書,美團,網易等等(Java崗)
  32. Rétrospectivement, j'ai passé deux mois à interviewer Ali, ctrip, Little Red Book, meituan, NetEase, etc. (Java post)
  33. Docker + webhook Automation Deployment Front End Project
  34. Java技术之Spring、Hibernate框架整合方法
  35. http://lx.gongxuanwang.com/sszt/32.htm
  36. 亚马逊自己的 Linux 发行版现在完全基于 Fedora 了
  37. Redis 源码简洁剖析 02 - SDS 字符串
  38. Java技術之Spring、Hibernate框架整合方法
  39. Méthode d'intégration des cadres de printemps et d'hibernation de la technologie Java
  40. Redis source Concise Analysis 02 - SDS String
  41. La distribution Linux d'Amazon est maintenant entièrement basée sur Fedora
  42. org.springframework.web.bind.MissingServletRequestParameterException
  43. Built in constraints and functions of MySQL Foundation (2)
  44. Basic operation of MySQL Foundation (I)
  45. Introduction to Java zero foundation 3: Java data types
  46. 从零开始搭建EasyDarwin环境——Linux系统开发环境搭建Golang
  47. Redis source Concise Analysis 02 - SDS String
  48. Construire l'environnement easydarwin à partir de zéro - - construire l'environnement de développement du système Linux golang
  49. javaweb代码是正确的,但是第一行代码就报错了
  50. **** | Java | 后端开挂:3行代码写出8个接口
  51. Java || 看了大二学长写的代码,我竟开始默默的模仿了。。。
  52. Java | 手把手教你实现一个抽奖系统(Java版)
  53. Java | Manuel pour vous apprendre à mettre en œuvre un système de loterie (version Java)
  54. Java | | après avoir lu le Code que j'ai écrit en deuxième année, j'ai commencé à imiter silencieusement...
  55. Java | back - end Pending: 3 - line Code write 8 Interfaces
  56. Le Code Web Java est correct, mais la première ligne de code est incorrecte
  57. Android网络编程之Http通信
  58. Android網絡編程之Http通信
  59. Http communication for Android Network Programming
  60. The story of spring