@@ -35,20 +35,60 @@ namespace Xamarin.Android.Tools.Bytecode
3535{
3636 enum JavaDocKind {
3737 DroidDoc ,
38+ DroidDoc2 ,
3839 Java6 ,
39- Java7
40+ Java7 ,
41+ Java8
4042 }
4143
4244 class DroidDocScraper : AndroidDocScraper
4345 {
4446 const String pattern_head_droiddoc = "<span class=\" sympad\" ><a href=\" .*" ;
45-
47+
4648 public DroidDocScraper ( string dir )
4749 : base ( dir , pattern_head_droiddoc , null , " " , false )
4850 {
4951 }
5052 }
5153
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+
5292 class JavaDocScraper : AndroidDocScraper
5393 {
5494 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
80120 const String parameter_pair_splitter_javadoc = " " ;
81121
82122 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 )
84124 {
85125 }
86126 }
@@ -94,14 +134,15 @@ public abstract class AndroidDocScraper
94134 readonly String open_method ;
95135 readonly String param_sep ;
96136 readonly String close_method ;
137+ readonly String post_close_method_parens ;
97138 string root ;
98-
139+
99140 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 )
101142 {
102143 }
103144
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 )
105146 {
106147 if ( dir == null )
107148 throw new ArgumentNullException ( "dir" ) ;
@@ -112,7 +153,8 @@ protected AndroidDocScraper (string dir, String patternHead, String resetPattern
112153 continuous_param_lines = continuousParamLines ;
113154 open_method = openMethod ;
114155 param_sep = paramSep ;
115- close_method = closeMethod ;
156+ close_method = closeMethod ;
157+ post_close_method_parens = postCloseMethodParens ?? string . Empty ;
116158 if ( ! Directory . Exists ( dir ) )
117159 throw new Exception ( "Directory '" + dir + "' does not exist" ) ;
118160
@@ -124,18 +166,22 @@ protected AndroidDocScraper (string dir, String patternHead, String resetPattern
124166 //foreach (var f in Directory.GetFiles (dir, "*.html", SearchOption.AllDirectories))
125167 // LoadDocument (f.Substring (dir.Length + 1), f);
126168 }
127-
128- void LoadDocument ( string packageDir , string file )
169+
170+ protected virtual IEnumerable < string > GetContentLines ( string path )
129171 {
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 ) ;
134180 }
135181
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 )
137183 {
138- String path = package . Replace ( '.' , '/' ) + '/' + type . Replace ( '$' , '.' ) + ".html" ;
184+ string path = package . Replace ( '.' , '/' ) + '/' + type . Replace ( '$' , '.' ) + ".html" ;
139185 string file = Path . Combine ( root , path ) ;
140186 if ( ! File . Exists ( file ) ) {
141187 Log . Warning ( 1 , "Warning: no document found : " + file ) ;
@@ -153,44 +199,39 @@ public String[] GetParameterNames (string package, string type, string method, s
153199 buffer . Append ( param_sep ) ;
154200 buffer . Append ( ptypes [ i ] . Replace ( '$' , '.' ) ) ;
155201 }
202+ buffer . Replace ( "[" , "\\ [" ) . Replace ( "]" , "\\ ]" ) ;
156203 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 ( "?" , "\\ ?" ) ;
159207 Regex pattern = new Regex ( buffer . ToString ( ) , RegexOptions . Multiline ) ;
160208
161209 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 ] ;
184228 }
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 ;
191230 }
192- } finally {
193- reader . Close ( ) ;
231+ if ( ShouldResetMatchBuffer ( text ) )
232+ prev = null ;
233+ else
234+ prev = text ;
194235 }
195236 } catch ( Exception e ) {
196237 Log . Error ( "ERROR in {0}.{1}: {2}" , type , method , e ) ;
0 commit comments