Skip to content

Commit bb9f2d6

Browse files
committed
0.15.4 - Fixes for parameter annotation parsing, and generic type parameter parsing, and C# parameter annotation parsing.
1 parent 7704ebf commit bb9f2d6

26 files changed

+323
-180
lines changed

.classpath

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<classpathentry kind="src" path="src"/>
44
<classpathentry kind="src" path="plugins"/>
55
<classpathentry kind="src" path="test"/>
6-
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jre-9.0.1">
6+
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
77
<attributes>
88
<attribute name="module" value="true"/>
99
<attribute name="limit-modules" value="java.se,java.xml.ws.annotation"/>
@@ -14,7 +14,6 @@
1414
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Lombok"/>
1515
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/TemplateUtil"/>
1616
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/TestChecks"/>
17-
<classpathentry kind="output" path="bin"/>
1817
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jackson/jar/jackson-annotations-2.5.0.jar" sourcepath="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jackson/src/jackson-annotations-2.5.0-sources.jar">
1918
<attributes>
2019
<attribute name="javadoc_location" value="jar:file:/C:/Users/TeamworkGuy2/Documents/Java/Libraries/jackson/doc/jackson-annotations-2.5.0-javadoc.jar!/"/>
@@ -55,4 +54,5 @@
5554
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jtree-walker/bin/jtree_walker.jar" sourcepath="/JTreeWalker"/>
5655
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jtuples/bin/jtuples.jar" sourcepath="/JTuples"/>
5756
<classpathentry kind="lib" path="C:/Users/TeamworkGuy2/Documents/Java/Libraries/jtwg2-logging/bin/jtwg2_logging.jar" sourcepath="/JTwg2Logging"/>
57+
<classpathentry kind="output" path="bin"/>
5858
</classpath>

CHANGELOG.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,26 @@ This project does its best to adhere to [Semantic Versioning](http://semver.org/
44

55

66
--------
7-
### [0.15.3](N/A) - 2017-12-30
7+
### [0.15.4](N/A) - 2018-09-13
8+
#### Added
9+
* Annotations to parameter signatures (with basic parameter annotation parsing added to `MethodParametersParser.extractParamsFromSignature()`)
10+
* Documented DataTypeExtractor methods
11+
* Added/Improved test cases for:
12+
* Class signatures (generics, multiple extend/implement types)
13+
* Generic types with multiple parameters
14+
* Annotations on method parameters
15+
* TODO: fix failing test for default parameters
16+
17+
#### Removed
18+
* Old code from MainParser
19+
20+
#### Fixed
21+
* `CsBlockParser.readClassIdentifierAndExtends()` was incorrectly trying to parse `new {` object initializer blocks as class declarations
22+
* DataTypeExtractor was reversing the parameter order of multi-paremeter generic types
23+
24+
25+
--------
26+
### [0.15.3](https://github.com/TeamworkGuy2/JParseCode/commit/7704ebf8f49e2841dc9e362fef1752252e283b71) - 2017-12-30
827
#### Changed
928
* Update dependency `jtwg2-logging@0.3.0`
1029

README.md

+45-45
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
JParseCode
22
==============
3-
version: 0.15.3
3+
version: 0.15.4
44

5-
In progress C#/Java/TypeScript parser tools built atop [JTextParser] (https://github.com/TeamworkGuy2/JTextParser), [Jackson] (https://github.com/FasterXML/jackson-core/) (core, databind, annotations) and half a dozen other utility libraries.
5+
In progress C#/Java/TypeScript parser tools built atop [JTextParser](https://github.com/TeamworkGuy2/JTextParser), [Jackson](https://github.com/FasterXML/jackson-core/) (core, databind, annotations) and half a dozen other utility libraries.
66

77
### Goals:
88
* A source code parser that can turn C#, Java, or JavaScript/TypeScript code into a simple AST like structure ('competent' meaning this project aims to support common use cases, not every syntatic feature of the supported languages).
@@ -18,60 +18,60 @@ Example:
1818

1919
Source Code (SimpleCs.cs):
2020
```C#
21-
namespace ParserExamples.Samples {
21+
namespace ParserExamples.Samples {
2222

23-
/// <summary>
24-
/// A simple class to test parsing.
25-
/// </summary>
26-
public class SimpleCs {
23+
/// <summary>
24+
/// A simple class to test parsing.
25+
/// </summary>
26+
public class SimpleCs {
2727

28-
/// <value>The modification count.</value>
29-
private int mod;
28+
/// <value>The modification count.</value>
29+
private int mod;
3030

31-
/// <value>The name.</value>
32-
private string _name;
31+
/// <value>The name.</value>
32+
private string _name;
3333

34-
/// <value>The names.</value>
35-
public IList<string> Names { get; }
34+
/// <value>The names.</value>
35+
public IList<string> Names { get; }
3636

37-
/// <value>The number of names.</value>
38-
public int Count { set; }
37+
/// <value>The number of names.</value>
38+
public int Count { set; }
3939

40-
/// <value>The access timestamps.</value>
41-
public DateTime[] accesses { set { this.mod++; this.accesses = value; } }
40+
/// <value>The access timestamps.</value>
41+
public DateTime[] accesses { set { this.mod++; this.accesses = value; } }
4242

43-
/// <value>The access timestamps.</value>
44-
public string name { get { this.mod++; return this._name; } set { this.mod++; this._name = value; } }
45-
46-
/// <summary>Add name</summary>
47-
/// <param name="name">the name</param>
48-
/// <returns>the names</returns>
49-
[OperationContract]
50-
[WebInvoke(Method = "POST", UriTemplate = "/AddName?name={name}",
51-
ResponseFormat = WebMessageFormat.Json)]
52-
[TransactionFlow(TransactionFlowOption.Allowed)]
53-
Result<IList<String>> AddName(string name) {
54-
content of block;
55-
}
43+
/// <value>The access timestamps.</value>
44+
public string name { get { this.mod++; return this._name; } set { this.mod++; this._name = value; } }
5645

46+
/// <summary>Add name</summary>
47+
/// <param name="name">the name</param>
48+
/// <returns>the names</returns>
49+
[OperationContract]
50+
[WebInvoke(Method = "POST", UriTemplate = "/AddName?name={name}",
51+
ResponseFormat = WebMessageFormat.Json)]
52+
[TransactionFlow(TransactionFlowOption.Allowed)]
53+
Result<IList<String>> AddName(string name) {
54+
content of block;
5755
}
5856

5957
}
58+
59+
}
6060
```
6161

6262

6363
Java code to parser SimpleCs.cs (simple_cs_source_string is a string containing the contents of SimpleCs.cs):
6464
```Java
65-
CodeFileSrc<CodeLanguage> simpleCsAst = ParseCodeFile.parseCode("SimpleCs.cs", CodeLanguageOptions.C_SHARP, simple_cs_source_string);
66-
WriteSettings ws = new WriteSettings(true, true, true, true);
67-
68-
for(Map.Entry<SimpleTree<CodeToken>, ClassAst.SimpleImpl<CsBlock>> block : CodeLanguageOptions.C_SHARP.getExtractor().extractClassFieldsAndMethodSignatures(simpleCsAst.getDoc())) {
69-
CodeFileParsed.Simple<String, CsBlock> fileParsed = new CodeFileParsed.Simple<>("SimpleCs.cs", block.getValue(), block.getKey());
70-
71-
StringBuilder sb = new StringBuilder();
72-
fileParsed.getParsedClass().toJson(sb, ws);
73-
System.out.println(sb.toString()); // Print the parsed AST to System.out
74-
}
65+
CodeFileSrc<CodeLanguage> simpleCsAst = ParseCodeFile.parseCode("SimpleCs.cs", CodeLanguageOptions.C_SHARP, simple_cs_source_string);
66+
WriteSettings ws = new WriteSettings(true, true, true, true);
67+
68+
for(Map.Entry<SimpleTree<CodeToken>, ClassAst.SimpleImpl<CsBlock>> block : CodeLanguageOptions.C_SHARP.getExtractor().extractClassFieldsAndMethodSignatures(simpleCsAst.getDoc())) {
69+
CodeFileParsed.Simple<String, CsBlock> fileParsed = new CodeFileParsed.Simple<>("SimpleCs.cs", block.getValue(), block.getKey());
70+
71+
StringBuilder sb = new StringBuilder();
72+
fileParsed.getParsedClass().toJson(sb, ws);
73+
System.out.println(sb.toString()); // Print the parsed AST to System.out
74+
}
7575
```
7676

7777

@@ -190,10 +190,10 @@ path/to/java -jar path/to/jparse-code.jar
190190
-log './output/parser.log'
191191
```
192192
Where ./src/java/Server/** is where source files are kept
193-
And the files in ./src/java/Server/Services belong to the C# namespace 'App.Services' and ./src/java/Server/Models/ belong to the C# namespace 'App.Entities'
193+
And the files in ./src/java/Server/Services belong to the C# namespace `App.Services` and ./src/java/Server/Models/ belong to the C# namespace `App.Entities`
194194

195195

196-
###Sources
196+
#### Sources
197197
A semicolon separated list of paths set equal to a directory depth followed by a comma and a comma separated, brackets wrapped, list of file extensions.
198198
The path, child directory depth, and file extensions are used to create a file system filter and all matching files are parsed.
199199
The following formats are valid:
@@ -202,18 +202,18 @@ The following formats are valid:
202202
'path'
203203

204204
Example: ```/project/myApp/Models=3,[java,json]```
205-
Note: the brackets around '[fileExt]' are literal.
205+
Note: the brackets around the '[java,json]' file extension list are literal.
206206

207207

208-
###Destinations
208+
#### Destinations
209209
A semicolon separated list of output file names associated with lists of namespaces. Each parsed file who's namespace falls into one of these lists is written to that file.
210210
The following format is valid:
211211
'path=[namespace,namespace,...]'
212212

213213
Example: ```/project/output/models.json=[MyApp.Models]```
214214

215215

216-
####Log
216+
#### Log
217217
An optional log file name to write parser information to, in the format:
218218
'path'
219219

bin/jparse_code-with-tests.jar

-545 Bytes
Binary file not shown.

bin/jparse_code.jar

-498 Bytes
Binary file not shown.

package-lib.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version" : "0.15.3",
2+
"version" : "0.15.4",
33
"name" : "jparse-code",
44
"description" : "An in-progress suite of parsing/transpilation tools for C#, Java, and TypeScript code. Generates simple JSON ASTs.",
55
"homepage" : "https://github.com/TeamworkGuy2/JParseCode",

rsc/csharp/ParserExamples/Services/ITrackSearchService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public interface ITrackSearchService
2323
[WebInvoke(Method = "POST", UriTemplate = "/TrackSearch",
2424
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
2525
[TransactionFlow(TransactionFlowOption.Allowed)]
26-
SearchResult<TrackInfo> Search(TrackSearchCriteria criteria) { ; }
26+
SearchResult<TrackInfo<string>, AlbumInfo<string>> Search(TrackSearchCriteria criteria) { ; }
2727

2828
/// <summary>
2929
/// Searches tracks that have past due date.

rsc/java/ParserExamples/Services/ITrackSearchService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
package ParserExamples.Services;import System.ServiceModel;import System.ServiceModel.Web;import ParserExamples.Models;import ParserExamples.Searching;/// <summary>/// This interface provides the contract for track searching./// </summary>/// <remarks>/// Implementations are expected to be effectively thread-safe./// </remarks>[ServiceContract]public interface ITrackSearchService{ /// <summary> /// Searches tracks. /// </summary> /// <param name="criteria">The search criteria</param> /// <returns>The search result</returns> @OperationContract @WebInvoke(Method = "POST", UriTemplate = "/TrackSearch", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json) @TransactionFlow(TransactionFlowOption.Allowed) SearchResult<TrackInfo> Search(TrackSearchCriteria criteria) { ; } /// <summary> /// Searches tracks that have past due date. /// </summary> /// <param name="albumName">The album name</param> /// <returns>The search result</returns> @OperationContract @WebInvoke(Method = "POST", UriTemplate = "/GetAlbumTracks?albumName={albumName}", ResponseFormat = WebMessageFormat.Json) @TransactionFlow(TransactionFlowOption.Allowed) SearchResult<Dictionary<AlbumInfo, List<TrackInfo>>> GetAlbumTracks(String albumName) { content of block; }}
1+
package ParserExamples.Services;import System.ServiceModel;import System.ServiceModel.Web;import ParserExamples.Models;import ParserExamples.Searching;/// <summary>/// This interface provides the contract for track searching./// </summary>/// <remarks>/// Implementations are expected to be effectively thread-safe./// </remarks>[ServiceContract]public interface ITrackSearchService{ /// <summary> /// Searches tracks. /// </summary> /// <param name="criteria">The search criteria</param> /// <returns>The search result</returns> @OperationContract @WebInvoke(Method = "POST", UriTemplate = "/TrackSearch", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json) @TransactionFlow(TransactionFlowOption.Allowed) SearchResult<TrackInfo<String>, AlbumInfo<String>> Search(TrackSearchCriteria criteria) { ; } /// <summary> /// Searches tracks that have past due date. /// </summary> /// <param name="albumName">The album name</param> /// <returns>The search result</returns> @OperationContract @WebInvoke(Method = "POST", UriTemplate = "/GetAlbumTracks?albumName={albumName}", ResponseFormat = WebMessageFormat.Json) @TransactionFlow(TransactionFlowOption.Allowed) SearchResult<Dictionary<AlbumInfo, List<TrackInfo>>> GetAlbumTracks(String albumName) { content of block; }}

src/twg2/ast/interm/annotation/AnnotationSig.java

+44
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,48 @@ public String toString() {
4545
return "annotation: " + name + "(" + arguments + ")";
4646
}
4747

48+
49+
@Override
50+
public int hashCode() {
51+
final int prime = 31;
52+
int result = 1;
53+
result = prime * result + (arguments == null ? 0 : arguments.hashCode());
54+
result = prime * result + (fullName == null ? 0 : fullName.hashCode());
55+
result = prime * result + (name == null ? 0 : name.hashCode());
56+
return result;
57+
}
58+
59+
60+
@Override
61+
public boolean equals(Object obj) {
62+
if (this == obj)
63+
return true;
64+
if (obj == null || this.getClass() != obj.getClass())
65+
return false;
66+
67+
AnnotationSig other = (AnnotationSig) obj;
68+
if (arguments == null) {
69+
if (other.arguments != null)
70+
return false;
71+
}
72+
else if (!arguments.equals(other.arguments))
73+
return false;
74+
75+
if (fullName == null) {
76+
if (other.fullName != null)
77+
return false;
78+
}
79+
else if (!fullName.equals(other.fullName))
80+
return false;
81+
82+
if (name == null) {
83+
if (other.name != null)
84+
return false;
85+
}
86+
else if (!name.equals(other.name))
87+
return false;
88+
89+
return true;
90+
}
91+
4892
}

src/twg2/ast/interm/method/ParameterSig.java

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import lombok.Getter;
88
import lombok.val;
99
import twg2.annotations.Immutable;
10+
import twg2.ast.interm.annotation.AnnotationSig;
1011
import twg2.io.json.stringify.JsonStringify;
1112
import twg2.parser.codeParser.AccessModifier;
1213
import twg2.parser.output.JsonWritableSig;
@@ -22,6 +23,7 @@ public class ParameterSig implements JsonWritableSig {
2223
final @Getter String name;
2324
final @Getter String typeSimpleName;
2425
final @Getter List<AccessModifier> parameterModifiers;
26+
final @Getter List<AnnotationSig> annotations;
2527
final @Getter boolean optional;
2628
final @Getter String defaultValue;
2729

@@ -38,6 +40,11 @@ public void toJson(Appendable dst, WriteSettings st) throws IOException {
3840
json.comma(dst).propName("parameterModifiers", dst)
3941
.toStringArray(parameterModifiers, dst, (acs) -> acs.toSrc());
4042

43+
if(annotations != null) {
44+
json.comma(dst).propName("annotations", dst)
45+
.toArrayConsume(annotations, dst, (ann) -> ann.toJson(dst, st));
46+
}
47+
4148
if(optional) {
4249
json.comma(dst).toProp("optional", optional, dst);
4350
}

src/twg2/ast/interm/method/ParameterSigResolved.java

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import lombok.Getter;
88
import lombok.val;
99
import twg2.annotations.Immutable;
10+
import twg2.ast.interm.annotation.AnnotationSig;
1011
import twg2.ast.interm.type.TypeSig;
1112
import twg2.io.json.stringify.JsonStringify;
1213
import twg2.parser.codeParser.AccessModifier;
@@ -23,6 +24,7 @@ public class ParameterSigResolved implements JsonWritableSig {
2324
final @Getter String name;
2425
final @Getter TypeSig.TypeSigResolved type;
2526
final @Getter List<AccessModifier> parameterModifiers;
27+
final @Getter List<AnnotationSig> annotations;
2628
final @Getter boolean optional;
2729
final @Getter String defaultValue;
2830

@@ -41,6 +43,11 @@ public void toJson(Appendable dst, WriteSettings st) throws IOException {
4143
json.comma(dst).propName("parameterModifiers", dst)
4244
.toStringArray(parameterModifiers, dst, (acs) -> acs.toSrc());
4345

46+
if(annotations != null) {
47+
json.comma(dst).propName("annotations", dst)
48+
.toArrayConsume(annotations, dst, (ann) -> ann.toJson(dst, st));
49+
}
50+
4451
if(optional) {
4552
json.comma(dst).toProp("optional", optional, dst);
4653
}

src/twg2/parser/codeParser/csharp/CsBlockParser.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ public static void _extractBlocksFromTree(List<String> nameScope, SimpleTree<Cod
170170
* @return {@code <className, extendImplementNames>}
171171
*/
172172
private static Entry<String, List<String>> readClassIdentifierAndExtends(EnhancedListBuilderIterator<SimpleTree<CodeToken>> iter) {
173-
val lang = CodeLanguageOptions.C_SHARP;
173+
val keywords = CodeLanguageOptions.C_SHARP.getKeywordUtil();
174174
// class signatures are read backward from the opening '{'
175175
int prevCount = 0;
176176
val names = new ArrayList<String>();
@@ -180,8 +180,11 @@ private static Entry<String, List<String>> readClassIdentifierAndExtends(Enhance
180180
if(iter.hasPrevious()) { prevCount++; }
181181
SimpleTree<CodeToken> prevNode = iter.hasPrevious() ? iter.previous() : null;
182182

183-
// TODO should read ', ' between each name, currently only works with 1 extend/implement class name
184-
while(prevNode != null && AstFragType.isIdentifierOrKeyword(prevNode.getData()) && !lang.getKeywordUtil().blockModifiers().is(prevNode.getData()) && !lang.getKeywordUtil().isInheritanceKeyword(prevNode.getData().getText())) {
183+
while(prevNode != null && AstFragType.isIdentifierOrKeyword(prevNode.getData()) && !keywords.blockModifiers().is(prevNode.getData()) && !keywords.isInheritanceKeyword(prevNode.getData().getText())) {
184+
// found an object initializer in the form 'new [Abc] {', not a class/interface definition so return nothing
185+
if(names.size() < 2 && CsKeyword.NEW.toSrc().equals(prevNode.getData().getText())) {
186+
break;
187+
}
185188
names.add(prevNode.getData().getText());
186189
prevNode = iter.hasPrevious() ? iter.previous() : null;
187190
if(iter.hasPrevious()) { prevCount++; }
@@ -191,7 +194,7 @@ private static Entry<String, List<String>> readClassIdentifierAndExtends(Enhance
191194
if(prevNode != null && prevNode.getData().getText().equals(":")) {
192195
prevNode = iter.hasPrevious() ? iter.previous() : null;
193196
if(iter.hasPrevious()) { prevCount++; }
194-
if(prevNode != null && AstFragType.isIdentifierOrKeyword(prevNode.getData()) && !lang.getKeywordUtil().blockModifiers().is(prevNode.getData())) {
197+
if(prevNode != null && AstFragType.isIdentifierOrKeyword(prevNode.getData()) && !keywords.blockModifiers().is(prevNode.getData())) {
195198
Collections.reverse(names);
196199
val extendImplementNames = names;
197200
val className = prevNode.getData().getText();

0 commit comments

Comments
 (0)