A semantic search engine for source code https://bitshift.benkurtovic.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

215 lines
7.3 KiB

  1. package com.bitshift.parsing.parsers;
  2. import java.util.HashMap;
  3. import java.util.List;
  4. import java.util.ArrayList;
  5. import java.util.Map;
  6. import java.util.Stack;
  7. import java.util.Arrays;
  8. import com.google.common.base.Joiner;
  9. import org.eclipse.jdt.core.JavaCore;
  10. import org.eclipse.jdt.core.dom.AST;
  11. import org.eclipse.jdt.core.dom.ASTNode;
  12. import org.eclipse.jdt.core.dom.ASTParser;
  13. import org.eclipse.jdt.core.dom.ASTVisitor;
  14. import org.eclipse.jdt.core.dom.CompilationUnit;
  15. import org.eclipse.jdt.core.dom.ClassInstanceCreation;
  16. import org.eclipse.jdt.core.dom.ImportDeclaration;
  17. import org.eclipse.jdt.core.dom.MethodDeclaration;
  18. import org.eclipse.jdt.core.dom.MethodInvocation;
  19. import org.eclipse.jdt.core.dom.Name;
  20. import org.eclipse.jdt.core.dom.PackageDeclaration;
  21. import org.eclipse.jdt.core.dom.QualifiedName;
  22. import org.eclipse.jdt.core.dom.SimpleName;
  23. import org.eclipse.jdt.core.dom.Statement;
  24. import org.eclipse.jdt.core.dom.TypeDeclaration;
  25. import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
  26. import com.bitshift.parsing.symbols.Symbols;
  27. import com.bitshift.parsing.symbols.JavaSymbols;
  28. /*TODO: Work on parsing partial java code.*/
  29. public class JavaParser {
  30. private String source;
  31. public JavaParser(String source) {
  32. this.source = source;
  33. }
  34. private Symbols genSymbols() {
  35. ASTParser parser = ASTParser.newParser(AST.JLS3);
  36. parser.setSource(this.source.toCharArray());
  37. Map options = JavaCore.getOptions();
  38. parser.setCompilerOptions(options);
  39. CompilationUnit root = (CompilationUnit) parser.createAST(null);
  40. NodeVisitor visitor = new NodeVisitor(root);
  41. root.accept(visitor);
  42. return visitor.symbols;
  43. }
  44. public String parse() {
  45. JavaSymbols symbols = (JavaSymbols) this.genSymbols();
  46. return symbols.toString();
  47. }
  48. class NodeVisitor extends ASTVisitor {
  49. protected CompilationUnit root;
  50. protected JavaSymbols symbols;
  51. private Stack<HashMap<String, Object>> _cache;
  52. public NodeVisitor(CompilationUnit root) {
  53. this.root = root;
  54. this.symbols = new JavaSymbols();
  55. this._cache = new Stack<HashMap<String, Object>>();
  56. }
  57. public ArrayList<Integer> blockPosition(ASTNode node) {
  58. int sl = this.root.getLineNumber(node.getStartPosition());
  59. int sc = this.root.getColumnNumber(node.getStartPosition()) + 1;
  60. int el = this.root.getLineNumber(node.getStartPosition()
  61. + node.getLength() - 1);
  62. int ec = this.root.getColumnNumber(node.getStartPosition()
  63. + node.getLength() - 1) + 1;
  64. return Symbols.createCoord(sl, sc, el, ec);
  65. }
  66. public boolean visit(MethodDeclaration node) {
  67. HashMap<String, Object> data = new HashMap<String, Object>();
  68. Name nameObj = node.getName();
  69. String name = nameObj.isQualifiedName() ?
  70. ((QualifiedName) nameObj).getFullyQualifiedName() :
  71. ((SimpleName) nameObj).getIdentifier();
  72. data.put("coord", this.blockPosition(node));
  73. data.put("name", name);
  74. this._cache.push(data);
  75. return true;
  76. }
  77. public void endVisit(MethodDeclaration node) {
  78. HashMap<String, Object> data = this._cache.pop();
  79. String name = (String)data.remove("name");
  80. this.symbols.insertMethodDeclaration("\"" + name + "\"", data);
  81. }
  82. public boolean visit(MethodInvocation node) {
  83. HashMap<String, Object> data = new HashMap<String, Object>();
  84. Name nameObj = node.getName();
  85. String name = nameObj.isQualifiedName() ?
  86. ((QualifiedName) nameObj).getFullyQualifiedName() :
  87. ((SimpleName) nameObj).getIdentifier();
  88. data.put("coord", this.blockPosition(node));
  89. data.put("name", name);
  90. this._cache.push(data);
  91. return true;
  92. }
  93. public void endVisit(MethodInvocation node) {
  94. HashMap<String, Object> data = this._cache.pop();
  95. String name = (String)data.remove("name");
  96. this.symbols.insertMethodInvocation("\"" + name + "\"", data);
  97. }
  98. public boolean visit(PackageDeclaration node) {
  99. HashMap<String, Object> data = new HashMap<String, Object>();
  100. this._cache.push(data);
  101. return true;
  102. }
  103. public void endVisit(PackageDeclaration node) {
  104. HashMap<String, Object> data = this._cache.pop();
  105. String name = (String)data.remove("name");
  106. this.symbols.setPackage(name);
  107. }
  108. public boolean visit(TypeDeclaration node) {
  109. HashMap<String, Object> data = new HashMap<String, Object>();
  110. data.put("coord", this.blockPosition(node));
  111. this._cache.push(data);
  112. return true;
  113. }
  114. public void endVisit(TypeDeclaration node) {
  115. HashMap<String, Object> data = this._cache.pop();
  116. String name = (String)data.remove("name");
  117. if (node.isInterface()) {
  118. this.symbols.insertInterfaceDeclaration("\"" + name + "\"", data);
  119. } else {
  120. this.symbols.insertClassDeclaration("\"" + name + "\"", data);
  121. }
  122. }
  123. public boolean visit(VariableDeclarationFragment node) {
  124. HashMap<String, Object> data = new HashMap<String, Object>();
  125. data.put("coord", this.blockPosition(node));
  126. this._cache.push(data);
  127. return true;
  128. }
  129. public void endVisit(VariableDeclarationFragment node) {
  130. HashMap<String, Object> data = this._cache.pop();
  131. String name = (String)data.remove("name");
  132. this.symbols.insertVariableDeclaration("\"" + name + "\"", data);
  133. }
  134. public boolean visit(QualifiedName node) {
  135. if (!this._cache.empty()) {
  136. HashMap<String, Object> data = this._cache.pop();
  137. if(!data.containsKey("name")) {
  138. String name = node.getFullyQualifiedName();
  139. data.put("name", name);
  140. }
  141. this._cache.push(data);
  142. }
  143. return true;
  144. }
  145. public boolean visit(SimpleName node) {
  146. if (!this._cache.empty()) {
  147. HashMap<String, Object> data = this._cache.pop();
  148. if(!data.containsKey("name")) {
  149. String name = node.getIdentifier();
  150. data.put("name", name);
  151. }
  152. this._cache.push(data);
  153. }
  154. return true;
  155. }
  156. public boolean visit(ImportDeclaration node) {
  157. HashMap<String, Object> data = new HashMap<String, Object>();
  158. data.put("coord", this.blockPosition(node));
  159. this._cache.push(data);
  160. return true;
  161. }
  162. public void endVisit(ImportDeclaration node) {
  163. HashMap<String, Object> data = this._cache.pop();
  164. String name = (String)data.remove("name");
  165. String[] parts = name.split("\\.");
  166. for(int i = parts.length; i > 1; i--) {
  167. String pkg = Joiner.on(".").join(Arrays.copyOfRange(parts, 0, i));
  168. this.symbols.insertImportStatement("\"" + pkg + "\"", data);
  169. }
  170. }
  171. }
  172. }