@@ -35,20 +35,60 @@ namespace Xamarin.Android.Tools.Bytecode
35
35
{
36
36
enum JavaDocKind {
37
37
DroidDoc ,
38
+ DroidDoc2 ,
38
39
Java6 ,
39
- Java7
40
+ Java7 ,
41
+ Java8
40
42
}
41
43
42
44
class DroidDocScraper : AndroidDocScraper
43
45
{
44
46
const String pattern_head_droiddoc = "<span class=\" sympad\" ><a href=\" .*" ;
45
-
47
+
46
48
public DroidDocScraper ( string dir )
47
49
: base ( dir , pattern_head_droiddoc , null , " " , false )
48
50
{
49
51
}
50
52
}
51
53
54
+ class DroidDoc2Scraper : AndroidDocScraper
55
+ {
56
+ const String pattern_head_droiddoc = "<tr class=\" api .+\" .*>.*<code>.*<a href=\" .*" ;
57
+ const String reset_pattern_head = "<p>" ;
58
+
59
+ public DroidDoc2Scraper ( string dir )
60
+ : base ( dir , pattern_head_droiddoc , reset_pattern_head , " " , true , "\\ (" , ", " , "\\ )" , "\\ s*</code>" )
61
+ {
62
+ }
63
+
64
+ string prev_path ;
65
+ string [ ] prev_contents ;
66
+
67
+ protected override IEnumerable < string > GetContentLines ( string path )
68
+ {
69
+ if ( prev_path == path )
70
+ return prev_contents ;
71
+ else {
72
+ prev_path = path ;
73
+ string all = File . ReadAllText ( path ) . Replace ( '\r ' , ' ' ) . Replace ( '\n ' , ' ' ) ;
74
+ int start = all . IndexOf ( "<!-- ======== START OF CLASS DATA ======== -->" , StringComparison . Ordinal ) ;
75
+ all = start < 0 ? all : all . Substring ( start ) ;
76
+ int end = all . IndexOf ( "<!-- ========= END OF CLASS DATA ========= -->" , StringComparison . Ordinal ) ;
77
+ all = end < 0 ? all : all . Substring ( 0 , end ) ;
78
+ // <tr>...</tr> is the basic structure so </tr> is used as the end of member, but we also use <p> here.
79
+ // Sometimes another </code> can appear after "</code>" (for the end of context member) and that messes regex match.
80
+ // So, with any <p>, we interrupt consecutive matches.
81
+ prev_contents = all . Split ( new string [ ] { "<p>" , "</tr>" } , StringSplitOptions . RemoveEmptyEntries ) ;
82
+ return prev_contents ;
83
+ }
84
+ }
85
+
86
+ protected override bool ShouldResetMatchBuffer ( string text )
87
+ {
88
+ return true ;
89
+ }
90
+ }
91
+
52
92
class JavaDocScraper : AndroidDocScraper
53
93
{
54
94
const String pattern_head_javadoc = "<TD><CODE><B><A HREF=\" [./]*" ; // I'm not sure how path could be specified... (./ , ../ , or even /)
@@ -80,7 +120,7 @@ class Java8DocScraper : AndroidDocScraper
80
120
const String parameter_pair_splitter_javadoc = " " ;
81
121
82
122
public Java8DocScraper ( string dir )
83
- : base ( dir , pattern_head_javadoc , reset_pattern_head_javadoc , parameter_pair_splitter_javadoc , true , "-" , "-" , "-" )
123
+ : base ( dir , pattern_head_javadoc , reset_pattern_head_javadoc , parameter_pair_splitter_javadoc , true , "-" , "-" , "-" , null )
84
124
{
85
125
}
86
126
}
@@ -94,14 +134,15 @@ public abstract class AndroidDocScraper
94
134
readonly String open_method ;
95
135
readonly String param_sep ;
96
136
readonly String close_method ;
137
+ readonly String post_close_method_parens ;
97
138
string root ;
98
-
139
+
99
140
protected AndroidDocScraper ( string dir , String patternHead , String resetPatternHead , String parameterPairSplitter , bool continuousParamLines )
100
- : this ( dir , patternHead , resetPatternHead , parameterPairSplitter , continuousParamLines , "\\ (" , ", " , "\\ )" )
141
+ : this ( dir , patternHead , resetPatternHead , parameterPairSplitter , continuousParamLines , "\\ (" , ", " , "\\ )" , null )
101
142
{
102
143
}
103
144
104
- protected AndroidDocScraper ( string dir , String patternHead , String resetPatternHead , String parameterPairSplitter , bool continuousParamLines , string openMethod , string paramSep , string closeMethod )
145
+ protected AndroidDocScraper ( string dir , String patternHead , String resetPatternHead , String parameterPairSplitter , bool continuousParamLines , string openMethod , string paramSep , string closeMethod , string postCloseMethodParens )
105
146
{
106
147
if ( dir == null )
107
148
throw new ArgumentNullException ( "dir" ) ;
@@ -112,7 +153,8 @@ protected AndroidDocScraper (string dir, String patternHead, String resetPattern
112
153
continuous_param_lines = continuousParamLines ;
113
154
open_method = openMethod ;
114
155
param_sep = paramSep ;
115
- close_method = closeMethod ;
156
+ close_method = closeMethod ;
157
+ post_close_method_parens = postCloseMethodParens ?? string . Empty ;
116
158
if ( ! Directory . Exists ( dir ) )
117
159
throw new Exception ( "Directory '" + dir + "' does not exist" ) ;
118
160
@@ -124,18 +166,22 @@ protected AndroidDocScraper (string dir, String patternHead, String resetPattern
124
166
//foreach (var f in Directory.GetFiles (dir, "*.html", SearchOption.AllDirectories))
125
167
// LoadDocument (f.Substring (dir.Length + 1), f);
126
168
}
127
-
128
- void LoadDocument ( string packageDir , string file )
169
+
170
+ protected virtual IEnumerable < string > GetContentLines ( string path )
129
171
{
130
- string pkgName = packageDir . Replace ( '/' , '.' ) ;
131
- string className = Path . GetFileNameWithoutExtension ( file ) . Replace ( '$' , '.' ) ;
132
-
133
- string html = File . ReadAllText ( file ) ;
172
+ return File . ReadAllText ( path ) . Split ( '\n ' ) ;
173
+ }
174
+
175
+ protected virtual bool ShouldResetMatchBuffer ( string text )
176
+ {
177
+ // sometimes we get incomplete tag, so cache it until it gets complete or matched.
178
+ // I *know* this is a hack.
179
+ return reset_pattern_head == null || text . EndsWith ( ">" , StringComparison . Ordinal ) || ! continuous_param_lines && ! text . StartsWith ( reset_pattern_head , StringComparison . Ordinal ) ;
134
180
}
135
181
136
- public String [ ] GetParameterNames ( string package , string type , string method , string [ ] ptypes , bool isVarArgs )
182
+ public virtual String [ ] GetParameterNames ( string package , string type , string method , string [ ] ptypes , bool isVarArgs )
137
183
{
138
- String path = package . Replace ( '.' , '/' ) + '/' + type . Replace ( '$' , '.' ) + ".html" ;
184
+ string path = package . Replace ( '.' , '/' ) + '/' + type . Replace ( '$' , '.' ) + ".html" ;
139
185
string file = Path . Combine ( root , path ) ;
140
186
if ( ! File . Exists ( file ) ) {
141
187
Log . Warning ( 1 , "Warning: no document found : " + file ) ;
@@ -153,44 +199,39 @@ public String[] GetParameterNames (string package, string type, string method, s
153
199
buffer . Append ( param_sep ) ;
154
200
buffer . Append ( ptypes [ i ] . Replace ( '$' , '.' ) ) ;
155
201
}
202
+ buffer . Replace ( "[" , "\\ [" ) . Replace ( "]" , "\\ ]" ) ;
156
203
buffer . Append ( close_method ) ;
157
- buffer . Append ( "\" .*\\ ((.*)\\ )" ) ;
158
- buffer . Replace ( "[" , "\\ [" ) . Replace ( "]" , "\\ ]" ) . Replace ( "?" , "\\ ?" ) ;
204
+ buffer . Append ( "\" .*\\ (([^(]*)\\ )" ) ;
205
+ buffer . Append ( post_close_method_parens ) ;
206
+ buffer . Replace ( "?" , "\\ ?" ) ;
159
207
Regex pattern = new Regex ( buffer . ToString ( ) , RegexOptions . Multiline ) ;
160
208
161
209
try {
162
- var reader = File . OpenText ( file ) ;
163
- try {
164
- String text = "" ;
165
- String prev = null ;
166
- while ( ( text = reader . ReadLine ( ) ) != null ) {
167
- if ( prev != null )
168
- prev = text = prev + text ;
169
- var matcher = pattern . Match ( text ) ;
170
- if ( matcher . Success ) {
171
- var plist = matcher . Groups [ 1 ] ;
172
- String [ ] parms = plist . Value . Split ( new string [ ] { ", " } , StringSplitOptions . RemoveEmptyEntries ) ;
173
- if ( parms . Length != ptypes . Length ) {
174
- Log . Warning ( 1 , "failed matching {0} (expected {1} params, got {2} params)" , buffer , ptypes . Length , parms . Length ) ;
175
- return null ;
176
- }
177
- String [ ] result = new String [ ptypes . Length ] ;
178
- for ( int i = 0 ; i < ptypes . Length ; i ++ ) {
179
- String [ ] toks = parms [ i ] . Split ( parameter_pair_splitter ) ;
180
- result [ i ] = toks [ toks . Length - 1 ] ;
181
- }
182
- reader . Close ( ) ;
183
- return result ;
210
+ String text = "" ;
211
+ String prev = null ;
212
+ foreach ( var _text in GetContentLines ( file ) ) {
213
+ text = _text . TrimEnd ( '\r ' ) ;
214
+ if ( prev != null )
215
+ prev = text = prev + text ;
216
+ var matcher = pattern . Match ( text ) ;
217
+ if ( matcher . Success ) {
218
+ var plist = matcher . Groups [ 1 ] ;
219
+ String [ ] parms = plist . Value . Split ( new string [ ] { ", " } , StringSplitOptions . RemoveEmptyEntries ) ;
220
+ if ( parms . Length != ptypes . Length ) {
221
+ Log . Warning ( 1 , "failed matching {0} (expected {1} params, got {2} params)" , buffer , ptypes . Length , parms . Length ) ;
222
+ return null ;
223
+ }
224
+ String [ ] result = new String [ ptypes . Length ] ;
225
+ for ( int i = 0 ; i < ptypes . Length ; i ++ ) {
226
+ String [ ] toks = parms [ i ] . Split ( parameter_pair_splitter ) ;
227
+ result [ i ] = toks [ toks . Length - 1 ] ;
184
228
}
185
- // sometimes we get incomplete tag, so cache it until it gets complete or matched.
186
- // I *know* this is a hack.
187
- if ( reset_pattern_head == null || text . EndsWith ( ">" , StringComparison . Ordinal ) || ! continuous_param_lines && ! text . StartsWith ( reset_pattern_head , StringComparison . Ordinal ) )
188
- prev = null ;
189
- else
190
- prev = text ;
229
+ return result ;
191
230
}
192
- } finally {
193
- reader . Close ( ) ;
231
+ if ( ShouldResetMatchBuffer ( text ) )
232
+ prev = null ;
233
+ else
234
+ prev = text ;
194
235
}
195
236
} catch ( Exception e ) {
196
237
Log . Error ( "ERROR in {0}.{1}: {2}" , type , method , e ) ;
0 commit comments