SalesforceFoundation / ApexDoc

The latest java source for ApexDoc, a tool to document your Salesforce Apex classes.
BSD 3-Clause "New" or "Revised" License
229 stars 128 forks source link

Invalid Arguments detected (NullPointerException) #56

Open jdcrensh opened 8 years ago

jdcrensh commented 8 years ago

Executing the program breaks with NullPointerException in ClassModel#compare. Paths given are relative to apexdoc.jar, which is in my project root (also tried absolute paths). The two html paths given in the parameters do exist.

The same error occurs when providing only the -s and -t flags (and only the -s flag), except that it shows nine lines of Error: null instead of two.

System: OS X El Capitan 10.11.3

$ java -version
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)
$ java -jar apexdoc.jar -s ./src/classes \
    -t ./docs \
    -p 'global;public;private;testmethod;webService' \
    -g https://example.com/repo/src/classes \
    -h ./homepage.html \
    -a ./projectheader.html
Error: null
Error: null
java.lang.NullPointerException
    at org.salesforce.apexdoc.ClassModel$1.compare(ClassModel.java:55)
    at org.salesforce.apexdoc.ClassModel$1.compare(ClassModel.java:1)
    at java.util.TimSort.binarySort(TimSort.java:292)
    at java.util.TimSort.sort(TimSort.java:217)
    at java.util.Arrays.sort(Arrays.java:1512)
    at java.util.ArrayList.sort(ArrayList.java:1454)
    at java.util.Collections.sort(Collections.java:175)
    at org.salesforce.apexdoc.ClassModel.getMethodsSorted(ClassModel.java:48)
    at org.salesforce.apexdoc.FileManager.htmlForClassModel(FileManager.java:217)
    at org.salesforce.apexdoc.FileManager.makeFile(FileManager.java:143)
    at org.salesforce.apexdoc.FileManager.createDoc(FileManager.java:429)
    at org.salesforce.apexdoc.ApexDoc.RunApexDoc(ApexDoc.java:128)
    at org.salesforce.apexdoc.ApexDoc.main(ApexDoc.java:36)
null
ApexDoc - a tool for generating documentation from Salesforce Apex code class files.

    Invalid Arguments detected.  The correct syntax is:

apexdoc -s <source_directory> [-t <target_directory>] [-g <source_url>] [-h <homefile>] [-a <authorfile>] [-p <scope>]

<source_directory> - The folder location which contains your apex .cls classes
<target_directory> - Optional. Specifies your target folder where documentation will be generated.
<source_url> - Optional. Specifies a URL where the source is hosted (so ApexDoc can provide links to your source).
<homefile> - Optional. Specifies the html file that contains the contents for the home page's content area.
<authorfile> - Optional. Specifies the text file that contains project information for the documentation header.
<scope> - Optional. Semicolon seperated list of scopes to document.  Defaults to 'global;public'.
jdcrensh commented 8 years ago

Interestingly, adding a blank access modifier (extra semicolon for private classes without modifier) to the -p flag stopped the error. But doing so seems to have caused an infinite loop (no output, never exits)...

$ java -jar apexdoc.jar -s ./src/classes -p 'global;public;private;;testmethod;webService'

Removing public from the -p list allows the docs to be generated for everything else (with a long list of Error: null).

If public is the only value in the -p list, docs are generated for public classes (still, lots of Error: null output). The moment I add another modifier, the error occurs.

Patlatus commented 8 years ago

I have the same error. @jdcrensh were you able to solve this or do you have workaround?

Patlatus commented 8 years ago

I use parameters "-s C:\Users\user\workspace\project\src\classes -t C:\Users\user\workspace\project\docs"

Patlatus commented 8 years ago

I have debugged this, a few lessons I have learned so far:

  1. The documentation is totally wrong; one doesn't have to put apostrophes to line "-p 'global;public;private;testmethod;webService'", instead we just just put "-p global;public;private;testmethod;webService".
  2. Null pointer exception happens on line 331 of ApexDoc.java class https://github.com/SalesforceFoundation/ApexDoc/blob/master/src/org/salesforce/apexdoc/ApexDoc.java#L331 because cModel == null if there is a class without any of directives like

@isTest class TestSomeTest {

Such classes are treated like private by Salesforce but misinterpreted by ApexDoc.

  1. If I put "-p global;public;private;;testmethod;webService" then probably it can avoid this error however looks like my version of this process running has hung and I can't be sure.
  2. There is another modification of apex doc by StevenWCox http://force-code.com/category/apexdoc/ which runs without errors just ignoring classes which are private but which do not have 'private' directive
eroispaziali commented 8 years ago

Hey guys, I know it's a bit off-topic but I am working on a cloud-based apex documentation tool. Still a working prototype with a few bugs, but the parsing is more robust and I would be very happy to get some feedback from real world projects if you want to give it a try. @Patlatus @jdcrensh

Patlatus commented 8 years ago

@eroispaziali, could you please share you code base? I have tried to run it but I believe it has got stuck. Probably if I look at the code I may understand why it has got stuck and why do you need so many permissions from the Salesforce organization

Patlatus commented 8 years ago

@eroispaziali Forcedocs is asking to:

Access your basic information Access and manage your data Provide access to your data via the Web Access and manage your Chatter data Provide access to custom applications Allow access to your unique identifier Access custom permissions Access and manage your Wave data Perform requests on your behalf at any time ???

Why this app needs so many permissions?

jdcrensh commented 8 years ago

@Patlatus I gave up trying to get around the error, but nice find on a maintained ApexDoc. I'll have to give that a shot. For anyone else reading this, it has a GitLab repo at StevenWCox/sfapexdoc.

bohdan-dovhan commented 8 years ago

@jdcrensh Yeah, I like it. I even tried to modify it and fix the markup it generates and to make it possible to generate VisualForce pages instead of html pages.

bohdan-dovhan commented 8 years ago

@jdcrensh By the way, I have eventually fixed this null-pointer exception, but after that I have found another big bug. I prefer Steven's version since that one doesn't have so many critical bugs

jdcrensh commented 8 years ago

@bohdan-dovhan Generating as VisualForce pages is a cool idea, but wouldn't that kind of pollute pages/ when there are a lot of classes? I have similar thought... How about packaging up the docs into a React/React-Router app as a static resource, which is served by a single page? I may put something like that together for the community when I have the time to revisit my documentation efforts, if I'm not beaten to it.

bohdan-dovhan commented 8 years ago

@jdcrensh Yeah, I totally agree that might pollute /pages/. So I was thinking about of packaging of all html files generated into a static resource itself (without any kind of react-router app), but it works if the size of compressed zip file is less than 5 Mb, if it is bigger, it is not possible to upload into Salesforce as a static resource

bohdan-dovhan commented 8 years ago

@jdcrensh I was also thinking of breaking the html files zipped into separate static resources, but in such case the interlinks will be broken. Also one junior developer from my team suggested to generate docs on the fly, but this solution requires too much development time. However, if we ever implemented this, it would be cool, since in such case we wouldn't have to use any kind of java application and we wouldn't have to retrieve classes first, then run java app, then load it back into a static resource or VisualForce pages or Google sites.

no-stack-dub-sack commented 5 years ago

@Patlatus the particular issue you referenced in this comment will be fixed once the first release of a newly maintained version of this project is made.

Now top-level classes that are not explicitly given an access modifier are assumed to be private (@isTest). This will also prevent the docs from ignoring inner classes not explicitly given an access modifier (which are also private by default)