/bundles/plugins-trunk/RubyPlugin/src/org/jedit/ruby/ri/RiParser.java

# · Java · 248 lines · 202 code · 24 blank · 22 comment · 20 complexity · ed66ff65f9b0b705f9a822f3ea1723f4 MD5 · raw file

  1. /*
  2. * RiParser.java -
  3. *
  4. * Copyright 2005 Robert McKinnon
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. package org.jedit.ruby.ri;
  21. import org.jedit.ruby.ast.*;
  22. import org.jedit.ruby.RubyPlugin;
  23. import org.jedit.ruby.utils.CommandUtils;
  24. import org.jedit.ruby.cache.RubyCache;
  25. import org.gjt.sp.jedit.jEdit;
  26. import java.io.*;
  27. import java.util.ArrayList;
  28. import java.util.List;
  29. import java.util.jar.JarEntry;
  30. import java.util.jar.JarInputStream;
  31. /**
  32. * @author robmckinnon at users.sourceforge.net
  33. */
  34. public final class RiParser {
  35. public static void parseRdoc() {
  36. RubyCache.resetCache();
  37. copyOverRubyCode();
  38. log("parsing RDoc from jar");
  39. List<JarEntry> entries = getEntries();
  40. for (JarEntry entry : entries) {
  41. loadClassDesciption(entry);
  42. }
  43. RubyCache.instance().populateSuperClassMethods();
  44. }
  45. private static List<String> getRDocExcludePatterns() {
  46. List<String> excludePatterns = new ArrayList<String>();
  47. if (!jEdit.getBooleanProperty(RDocViewer.INCLUDE_RAILS, true)) {
  48. excludePatterns.add("rails_2_3_2/Action");
  49. excludePatterns.add("rails_2_3_2/Active");
  50. excludePatterns.add("rails_2_3_2/Hpricot");
  51. }
  52. if (!jEdit.getBooleanProperty(RDocViewer.INCLUDE_RAILS_2_0, false)) {
  53. excludePatterns.add("rails_2_0_2/Action");
  54. excludePatterns.add("rails_2_0_2/Active");
  55. excludePatterns.add("rails_2_0_2/Hpricot");
  56. }
  57. return excludePatterns;
  58. }
  59. private static void copyOverRubyCode() {
  60. try {
  61. copyOverFile("rdoc_to_java.rb");
  62. copyOverFile("cdesc.erb");
  63. } catch (Exception e) {
  64. e.printStackTrace();
  65. RubyPlugin.error(e, RiParser.class);
  66. }
  67. }
  68. private static void copyOverFile(String name) throws IOException, InterruptedException {
  69. InputStream inputStream = RubyPlugin.class.getClassLoader().getResourceAsStream("ri/" + name);
  70. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
  71. File file = CommandUtils.getStoragePath(name);
  72. FileWriter writer = new FileWriter(file);
  73. String line;
  74. while((line = reader.readLine()) != null) {
  75. writer.write(line + '\n');
  76. }
  77. reader.close();
  78. writer.close();
  79. if(!CommandUtils.isWindows()) {
  80. CommandUtils.getOutput("chmod +x " + file.getPath(), false);
  81. }
  82. }
  83. private static void loadClassDesciption(JarEntry entry) {
  84. String name = entry.getName();
  85. InputStream inputStream = RubyPlugin.class.getClassLoader().getResourceAsStream(name);
  86. ObjectInputStream input = null;
  87. try {
  88. input = new ObjectInputStream(inputStream);
  89. ClassDescription result = (ClassDescription)input.readObject();
  90. String path = name.substring(name.lastIndexOf("/") + 1);
  91. cache(result, path);
  92. } catch (Exception e) {
  93. RubyPlugin.error(e, RiParser.class);
  94. } finally {
  95. try {
  96. if (input != null) {
  97. input.close();
  98. }
  99. } catch (IOException e) {
  100. RubyPlugin.error(e, RiParser.class);
  101. }
  102. }
  103. }
  104. private static List<JarEntry> getEntries() {
  105. List<JarEntry> entries = new ArrayList<JarEntry>();
  106. try {
  107. List<String> rdocExcludePatterns = getRDocExcludePatterns();
  108. JarInputStream jar = new JarInputStream(new FileInputStream(getJarFile()));
  109. JarEntry entry;
  110. while ((entry = jar.getNextJarEntry()) != null) {
  111. boolean includeEntry = !excludeEntry(rdocExcludePatterns, entry);
  112. if (includeEntry) {
  113. entries.add(entry);
  114. }
  115. }
  116. } catch (IOException e) {
  117. RubyPlugin.error(e, RiParser.class);
  118. }
  119. return entries;
  120. }
  121. private static boolean excludeEntry(List<String> rdocExcludePatterns, JarEntry entry) {
  122. boolean exclude = entry.isDirectory() || !entry.getName().endsWith(".dat");
  123. if (!exclude) {
  124. for (String excludePattern : rdocExcludePatterns) {
  125. if (entry.getName().indexOf(excludePattern) != -1) {
  126. exclude = true;
  127. break;
  128. }
  129. }
  130. }
  131. return exclude;
  132. }
  133. private static File getJarFile() {
  134. File file = getJarFile(jEdit.getSettingsDirectory());
  135. if(!file.exists()) {
  136. file = getJarFile(jEdit.getJEditHome());
  137. }
  138. log(file.getName());
  139. return file;
  140. }
  141. private static File getJarFile(String directory) {
  142. File dir = new File(directory, "jars");
  143. return new File(dir, "RubyPlugin.jar");
  144. }
  145. private static void cache(ClassDescription description, String path) {
  146. ClassMember parent = new ClassMember(description.getName());
  147. parent.setSuperClassName(description.getSuperclass());
  148. parent.setEndOffset(0);
  149. String namespace = description.getNamespace();
  150. if(namespace != null && namespace.trim().length() > 0) {
  151. namespace += "::";
  152. }
  153. parent.setNamespace(namespace);
  154. parent.setDocumentationComment(description.getComment());
  155. addMethods(description.getInstanceMethods(), parent);
  156. addMethods(description.getClassMethods(), parent);
  157. RubyCache.instance().addClass(parent, path);
  158. }
  159. private static void addMethods(List<MethodDescription> methods, ClassMember parent) {
  160. for (MethodDescription methodDescription : methods) {
  161. String name = methodDescription.getName();
  162. name = name.startsWith(".") ? name.substring(1) : name;
  163. Method method = new Method(name, null, "", "", methodDescription.isClassMethod());
  164. method.setNamespace(methodDescription.getNamespace());
  165. method.setDocumentationBlockParams(methodDescription.getBlockParameters());
  166. method.setDocumentationParams(methodDescription.getParameters());
  167. method.setDocumentationComment(methodDescription.getComment());
  168. method.setParentMemberName(parent.getName());
  169. method.setParentMember(null);
  170. method.setReceiver("", null);
  171. method.setEndOffset(0);
  172. parent.addChildMember(method);
  173. }
  174. }
  175. private static void log(String message) {
  176. RubyPlugin.log(message, RiParser.class);
  177. }
  178. public static void parse() {
  179. ClassDescription description = new ClassDescription();
  180. description.setAttributes(new ArrayList<Attribute>());
  181. List<MethodDescription> methods = new ArrayList<MethodDescription>();
  182. MethodDescription methodDescription = new MethodDescription();
  183. methodDescription.setName("new");
  184. methods.add(methodDescription);
  185. description.setClassMethods(methods);
  186. StringBuffer buffer = new StringBuffer();
  187. buffer.append("<tt>Object</tt> is the parent class of all classes in Ruby. Its methods are therefore available to all objects unless explicitly overridden.");
  188. buffer.append("<tt>Object</tt> mixes in the <tt>Kernel</tt> module, making the built-in kernel\n" +
  189. " functions globally accessible. Although the instance methods of <tt>Object</tt>\n" +
  190. " are defined by the <tt>Kernel</tt> module, we have chosen to document them here\n" +
  191. " for clarity.");
  192. buffer.append("In the descriptions of Object's methods, the parameter <em>symbol</em> refers to\n" +
  193. " a symbol, which is either a quoted string or a <tt>Symbol</tt> (such as\n" +
  194. " <tt>:name</tt>).");
  195. description.setComment(buffer.toString());
  196. description.setConstants(new ArrayList<Constant>());
  197. description.setFullName("Object");
  198. description.setName("Object");
  199. description.setSuperclass("");
  200. ArrayList<IncludedModule> includes = new ArrayList<IncludedModule>();
  201. IncludedModule includedModule = new IncludedModule();
  202. includedModule.setName("Kernel");
  203. includes.add(includedModule);
  204. description.setIncludes(includes);
  205. ArrayList<MethodDescription> instanceMethods = new ArrayList<MethodDescription>();
  206. MethodDescription method = new MethodDescription();
  207. method.setName("==");
  208. method.setAliases(new ArrayList<String>());
  209. method.setBlockParameters("e1, e2");
  210. method.setParameters(" obj == other => true or false\n" +
  211. " obj.equal?(other) => true or false\n" +
  212. " obj.eql?(other) => true or false");
  213. method.setComment(buffer.toString());
  214. method.setFullName("Object#==");
  215. method.setIsSingleton(true);
  216. method.setVisibility("public");
  217. method.setIsClassMethod(true);
  218. instanceMethods.add(method);
  219. method = new MethodDescription();
  220. method.setName("===");
  221. instanceMethods.add(method);
  222. description.setInstanceMethods(instanceMethods);
  223. }
  224. }