Project

Profile

Help

How to connect?
Download (21.6 KB) Statistics
| Branch: | Tag: | Revision:

he / tools / dotnet / parsecs.xsl @ 5d25f10d

1
<xsl:stylesheet version="3.0" 
2
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
4
   xmlns:f="http://local-functions/"
5
   exclude-result-prefixes="f xs">
6
  
7
  <xsl:output method="xml" indent="yes"/>
8
  
9
  <!-- This stylesheet reads the C# source code of the Saxon.Api component and extracts information from
10
     it that is not provided by the standard api-doc compiler output. This information is then merged
11
     with the api-doc.xml file to provide the input to the documentation generator -->
12
  
13
  <!-- Can use <c> or <code> tags within documentation comments to get code font in documentation. -->
14

    
15
  <xsl:param name="inputdir" required="yes"/>
16
  <xsl:variable name="files" select="
17
    'Configuration.cs',
18
    'Destination.cs',
19
    'Errors.cs',
20
    'Extensibility.cs',
21
    'Feature.cs',
22
    'FeatureKeys.cs',
23
    'Model.cs',
24
    'NamespaceConstant.cs',
25
    'Schema.cs',
26
    'Types.cs',
27
    'XPath.cs',
28
    'XQuery.cs',
29
    'Xslt.cs'"/>
30
  
31
  <xsl:template name="main">
32
    <xsl:sequence select="f:group(f:parse())"/>
33
  </xsl:template>
34
  
35
  <xsl:function name="f:parse" as="element(package)">  
36
    <package name="Saxon.Api">
37
      <xsl:for-each select="$files">
38
        <xsl:variable name="filename" select="concat($inputdir, '/', .)"/>
39
        <xsl:variable name="filecontent" select="unparsed-text($filename, 'iso-8859-1')"/>
40
        <xsl:variable name="filecontent" select="replace($filecontent, '/\*\*public\*\*/\s+', 'public ')"/>
41
        <xsl:variable name="lines" select="tokenize($filecontent, '\r?\n')"/>
42
        <xsl:for-each select="$lines">
43
          <xsl:variable name="line" select="normalize-space(.)"/>
44
          <xsl:choose>
45
            <xsl:when test="starts-with($line, 'using')">
46
              <!-- capture J-names and full types -->
47
              <xsl:variable name="tokens" select="tokenize(substring-after($line, 'using '), '\s')"/>
48
              <xsl:variable name="is-J-name" select="contains($line, '=')"/>
49
              <xsl:if test="$is-J-name">
50
                <xsl:variable name="J-name" select="$tokens[1]"/>
51
                <xsl:variable name="fulltype" select="translate($tokens[last()], ';@', '')"/>
52
                <using class="{$J-name}" fulltype="{$fulltype}"/>
53
              </xsl:if>
54
            </xsl:when>
55
            <xsl:when test="starts-with($line, 'namespace')">
56
              <!--<namespace name="{normalize-space(substring-after($line, 'namespace'))}"/>-->
57
            </xsl:when>
58
            <xsl:when test="$line = 'get' or starts-with($line, 'get {')">
59
              <get/>
60
            </xsl:when>
61
            <xsl:when test="$line = 'set' or starts-with($line, 'set {')">
62
              <set/>
63
            </xsl:when> 
64
            <xsl:when test="starts-with($line, '[Obsolete(')">
65
              <!-- If line contains + then go get next line too...  -->
66
              <xsl:variable name="position-of-first-line" select="position()"/>
67
              <!--<xsl:message expand-text="true">{$line}</xsl:message>-->
68
              <xsl:variable name="obsolete-strings" as="xs:string*">
69
                <xsl:iterate select="subsequence($lines, $position-of-first-line)">
70
                  <xsl:param name="position" select="$position-of-first-line"/>
71
                  <xsl:value-of select="substring-after(., '&quot;') => substring-before('&quot;')"/>
72
                  <xsl:choose>
73
                    <xsl:when test="ends-with($lines[$position], '+')">
74
                      <xsl:next-iteration>
75
                        <xsl:with-param name="position" select="$position +1"/>
76
                      </xsl:next-iteration>
77
                    </xsl:when>
78
                    <xsl:otherwise>
79
                      <xsl:break/>
80
                    </xsl:otherwise>
81
                  </xsl:choose>
82
                </xsl:iterate>
83
              </xsl:variable>
84
              <obsolete><xsl:value-of select="string-join($obsolete-strings, ' ')"/></obsolete>
85
            </xsl:when>
86
            <!-- Include internal classes (to later be removed in merge.xsl), so that any public
87
                methods inside them are not mistakenly attached to the wrong class -->
88
            <xsl:when test="starts-with($line, 'public') or starts-with($line, 'protected') or
89
              starts-with($line, 'internal')">
90
              <xsl:variable name="tokens" select="tokenize($line, '\s')"/>
91
              <xsl:variable name="is-class" select="$tokens = 'class'"/>
92
              <xsl:variable name="is-interface" select="$tokens = 'interface'"/>
93
              <xsl:variable name="is-enum" select="$tokens = 'enum'"/>
94
              <xsl:variable name="is-internal" select="$tokens = 'internal'"/>
95
              <xsl:variable name="is-public" select="$tokens = 'public'"/>
96
              <xsl:variable name="is-abstract" select="$tokens = 'abstract'"/>
97
              <xsl:variable name="is-virtual" select="$tokens = 'virtual'"/>
98
              <xsl:variable name="is-override" select="$tokens = 'override'"/>
99
              <xsl:variable name="is-static" select="$tokens = 'static'"/>
100
              <xsl:variable name="is-readonly" select="$tokens = 'readonly'"/>
101
              <xsl:variable name="is-initializer" select="contains($line, '=')"/>
102
              <xsl:variable name="is-method" select="contains($line, '(') and not($is-initializer)"/>
103
              
104
              <xsl:variable name="has-explicit-base" select="($is-enum or $is-class or $is-interface) and contains($line, ':')"/>
105
              <xsl:variable name="explicitBase" select="if ($has-explicit-base) 
106
                then normalize-space(translate(substring-after($line, ':'), '{', '')) else ()"/>
107
              <xsl:variable name="base" select="if ($has-explicit-base) then $explicitBase else 'object'"/>
108
              <xsl:variable name="line-pre-base" select="if ($has-explicit-base) then substring-before($line, ':') else $line"/>
109
              
110
              <xsl:variable name="is-generic-type" select="(not($is-method or $is-initializer) and contains($line-pre-base, '&lt;')) or 
111
                ($is-method and (substring-before($line, '(') => tokenize('\s'))[last()-1] => contains('&gt;')) or 
112
                ($is-initializer and substring-before($line, '=') => contains('&lt;'))"/>
113
              
114
              <xsl:variable name="is-generic-method" select="$is-method and
115
                ends-with(normalize-space(substring-before($line, '(')), '&gt;')"/>
116
              
117
              <xsl:variable name="method-input" select="if ($is-method) then
118
                (normalize-space(substring-before(substring-after($line, '('),')'))) else ''"/>
119
              <xsl:variable name="has-args" select="$is-method and ($method-input != '')"/>
120
              <!-- Can't always just tokenize $method-input on ','. 
121
                This is wrong when some argument has generic type with more than one type parameter. -->
122
              <xsl:variable name="method-args" as="xs:string*">
123
                <xsl:choose>
124
                  <xsl:when test="$has-args and matches($method-input, '^.*&lt;.*,.*&gt;')">
125
                    <!-- Method has some arg with generic type with more than one type parameter.
126
                      e.g. public void SetInitialTemplateParameters(Dictionary<QName, XdmValue> parameters, bool tunnel) 
127
                      First collapse spaces between &lt; and &gt; before tokenizing on ', '. -->
128
                    <xsl:variable name="collapse-space-seq" as="xs:string*">
129
                      <xsl:analyze-string select="$method-input" regex="{'&lt;.*,.*&gt;'}">
130
                        <xsl:matching-substring>
131
                          <xsl:value-of select="translate(., ' ', '')"/>
132
                        </xsl:matching-substring>
133
                        <xsl:non-matching-substring>
134
                          <xsl:value-of select="."/>
135
                        </xsl:non-matching-substring>
136
                      </xsl:analyze-string>
137
                    </xsl:variable>
138
                    <xsl:sequence select="tokenize(string-join($collapse-space-seq), ', ')"/>
139
                  </xsl:when>
140
                  <xsl:when test="$has-args">
141
                    <xsl:sequence select="tokenize($method-input, ',')"/>
142
                  </xsl:when>
143
                  <xsl:otherwise>
144
                    <xsl:value-of select="''"/>
145
                  </xsl:otherwise>
146
                </xsl:choose>
147
              </xsl:variable>
148
              
149
              <xsl:variable name="name">
150
                <xsl:choose>
151
                  <xsl:when test="$has-explicit-base and not($is-generic-type)">
152
                    <xsl:choose>
153
                      <xsl:when test="$tokens = ':'">
154
                        <xsl:sequence select="$tokens[index-of($tokens, ':')-1]"/>
155
                      </xsl:when>
156
                      <xsl:otherwise>
157
                        <xsl:variable name="nameToken" select="$tokens[contains(.,':')]"/>
158
                        <xsl:sequence select="substring-before($nameToken,':')"/>
159
                      </xsl:otherwise>
160
                    </xsl:choose>
161
                  </xsl:when>
162
                  <xsl:when test="$is-generic-method">
163
                    <xsl:sequence select="replace($line, '^.*\s([A-Za-z0-9_]+)&lt;([A-Za-z0-9_&gt;]+)\s*\(.*', '$1')"/>
164
                  </xsl:when>
165
                  <xsl:when test="$is-method">
166
                    <xsl:sequence select="replace($line, '^.*\s([A-Za-z0-9_]+)\s*\(.*', '$1')"/>
167
                  </xsl:when>
168
                  <xsl:when test="$is-initializer">
169
                    <xsl:analyze-string select="$line" regex="([A-Za-z0-9_]+)\s*=">
170
                      <xsl:matching-substring><xsl:sequence select="regex-group(1)"/></xsl:matching-substring>
171
                      <xsl:non-matching-substring></xsl:non-matching-substring>
172
                    </xsl:analyze-string>
173
                  </xsl:when>
174
                  <xsl:when test="$has-explicit-base and $is-generic-type and ($is-class or $is-interface)">
175
                    <!-- e.g. interface IXdmEnumerable<out XdmItem> : IEnumerable<XdmItem> -->
176
                    <xsl:sequence select="substring-before(tokenize($line-pre-base, '\s')[contains(., '&lt;')], '&lt;')"/>
177
                  </xsl:when>
178
                  <xsl:when test="$is-generic-type and ($is-class or $is-interface)">
179
                    <!-- e.g. class (e.g Feature<T>) or interface (e.g. Predicate<T>) -->
180
                    <xsl:sequence select="substring-before($tokens[not(. = ('{',
181
                      '{get;}','get;','set;','{set;}','}'))][contains(., '&lt;')][last()], '&lt;')"/>
182
                  </xsl:when>
183
                  <xsl:otherwise>
184
                    <xsl:sequence select="$tokens[not(. = ('{', '{get;}','get;','set;','{set;}','}'))][last()]"/>
185
                  </xsl:otherwise>
186
                </xsl:choose>
187
              </xsl:variable>
188
              
189
              <xsl:variable name="name" select="translate($name, ';', '')"/>
190
              
191
              <!-- Normally the type (of the property or method) is the token that appears before its name. 
192
                But this fails for a property where the name is the same as the type, e.g. "public Uri Uri". 
193
                So we handle this case specially.  -->
194
              <!-- Note that for constructors, $line is just something like "public A()"; then $type will be ''. -->
195
              <!-- Also need a special case if the type is a generic type with more than one type parameter
196
                e.g. Dictionary<QName, ParameterDetails> -->
197
              <xsl:variable name="type-is-name" select="count($tokens[translate(., ';', '') eq $name]) gt 1"/>
198
              <xsl:variable name="type">
199
                <xsl:choose>
200
                  <xsl:when test="$type-is-name">
201
                    <xsl:value-of select="$name"/>
202
                  </xsl:when>
203
                  <xsl:when test="$is-generic-type and ($is-class or $is-interface)">
204
                    <!-- e.g. class (e.g Feature<T>) or interface (e.g. Predicate<T>) 
205
                      here $type will include the type parameter part, e.g. Feature<T> -->
206
                    <xsl:variable name="string" select="if (ends-with($line-pre-base, '{')) then
207
                      substring-before($line-pre-base, '{') else $line-pre-base" />
208
                    <xsl:value-of select="concat($name, substring-after($string, $name))" />
209
                  </xsl:when>
210
                  <xsl:otherwise>
211
                    <!-- Note could still be wrong if we had something like "public Uri<T> Uri" i.e. name is part of type -->
212
                    <xsl:variable name="string" select="substring-before($line, concat(' ', $name))"/>
213
                    <xsl:choose>
214
                      <xsl:when test="$is-generic-type">
215
                        <xsl:variable name="Tclass" select="(substring-before($string,'&lt;')
216
                          => tokenize('\s'))[last()]"/>
217
                        <xsl:variable name="typeParams" select="concat('&lt;', substring-after($string,'&lt;')) 
218
                          => translate(' ', '')"/>
219
                        <xsl:value-of select="concat($Tclass, $typeParams)"/>
220
                      </xsl:when>
221
                      <xsl:otherwise>
222
                        <xsl:value-of select="tokenize($string, '\s')[last()][. != 'public']"/>
223
                        <!-- [. != 'public'] filter is for constructors; then $type is '' in this case -->
224
                      </xsl:otherwise>
225
                    </xsl:choose>
226
                  </xsl:otherwise>
227
                </xsl:choose>
228
              </xsl:variable>
229
              <!--<xsl:if test="$is-generic-type">
230
                <xsl:message expand-text="true">generic type: name {$name}</xsl:message>
231
                <xsl:message expand-text="true">generic type: type {$type}</xsl:message>
232
              </xsl:if>-->
233
              
234
              <xsl:choose>
235
                <xsl:when test="$is-class">
236
                  <class name="{$name}" public="{$is-public}" abstract="{$is-abstract}" static="{$is-static}" base="{$base}">
237
                    <xsl:if test="$is-internal">
238
                      <xsl:attribute name="internal" select="$is-internal"/>
239
                    </xsl:if>
240
                    <xsl:if test="$is-generic-type">
241
                      <!--<xsl:message>generic type class <xsl:value-of select="$name"/></xsl:message>-->
242
                      <xsl:sequence select="f:getTypeParamTypes($type)"/>
243
                    </xsl:if>
244
                  </class>
245
                </xsl:when>
246
                <xsl:when test="$is-interface">
247
                  <interface name="{$name}" public="{$is-public}" base="{$base}">
248
                    <xsl:if test="$is-internal">
249
                      <xsl:attribute name="internal" select="$is-internal"/>
250
                    </xsl:if>
251
                    <xsl:if test="$is-generic-type">
252
                      <!--<xsl:message>generic type interface <xsl:value-of select="$name"/></xsl:message>-->
253
                      <xsl:sequence select="f:getTypeParamTypes($type)"/>
254
                    </xsl:if>
255
                  </interface>
256
                </xsl:when>
257
                <xsl:when test="$is-enum">
258
                  <enum name="{$name}" public="{$is-public}" base="{$base}">
259
                    <xsl:if test="$is-internal">
260
                      <xsl:attribute name="internal" select="$is-internal"/>
261
                    </xsl:if>
262
                  </enum>
263
                </xsl:when>
264
                <xsl:when test="$is-method">
265
                  <method-or-constructor name="{$name}" public="{$is-public}" static="{$is-static}" abstract="{$is-abstract}" 
266
                    type="{if ($is-generic-type) then substring-before($type, '&lt;') else $type}"
267
                    override="{$is-override}" virtual="{$is-virtual}">
268
                    <xsl:if test="$is-generic-type">
269
                      <!--<xsl:message>generic type method <xsl:value-of select="$name"/></xsl:message>-->
270
                      <xsl:sequence select="f:getTypeParamTypes($type)"/>
271
                    </xsl:if>
272
                    <xsl:if test="$is-generic-method">
273
                      <!--<xsl:message>generic method <xsl:value-of select="$name"/></xsl:message>-->
274
                      <xsl:variable name="typeParams" as="xs:string*">
275
                        <xsl:sequence select="normalize-space(substring-before($line, '(')) => 
276
                          substring-after($name) => translate(' ', '') => f:getTypeParams()"/>
277
                      </xsl:variable>
278
                      <paramtypes>
279
                        <xsl:for-each select="$typeParams">
280
                          <type name="{.}"/>
281
                        </xsl:for-each>
282
                      </paramtypes>
283
                    </xsl:if>
284
                    <xsl:if test="$has-args">
285
                      <xsl:for-each select="$method-args">
286
                        <xsl:variable name="arg-type" select="substring-before(normalize-space(.),' ')"/>
287
                        <xsl:choose>
288
                          <xsl:when test="contains($arg-type, '&lt;')">
289
                            <param type="{substring-before($arg-type, '&lt;')}" name="{substring-after(normalize-space(.),' ')}">
290
                              <xsl:sequence select="f:getTypeParamTypes($arg-type)"/>
291
                            </param>
292
                          </xsl:when>
293
                          <xsl:otherwise>
294
                            <param type="{$arg-type}" name="{substring-after(normalize-space(.),' ')}"/>
295
                          </xsl:otherwise>
296
                        </xsl:choose>
297
                      </xsl:for-each>
298
                    </xsl:if>
299
                  </method-or-constructor>
300
                </xsl:when>
301
                <xsl:when test="$is-initializer">
302
                  <field name="{$name}" public="{$is-public}" static="{$is-static}" abstract="{$is-abstract}" 
303
                    override="{$is-override}" virtual="{$is-virtual}" readonly="{$is-readonly}"
304
                    type="{if ($is-generic-type) then substring-before($type, '&lt;') else $type}" >
305
                    <xsl:if test="$is-generic-type">
306
                      <!--<xsl:message>generic type field <xsl:value-of select="$name"/></xsl:message>-->
307
                      <xsl:sequence select="f:getTypeParamTypes($type)"/>
308
                    </xsl:if>
309
                  </field>
310
                </xsl:when>
311
                <xsl:otherwise>
312
                  <property initializer="{$is-initializer}" name="{$name}" public="{$is-public}" static="{$is-static}" readonly="{$is-readonly}" 
313
                    override="{$is-override}" virtual="{$is-virtual}" abstract="{$is-abstract}" 
314
                    type="{if ($is-generic-type) then substring-before($type, '&lt;') else $type}">
315
                    <xsl:if test="$is-generic-type">
316
                      <!--<xsl:message>generic type property <xsl:value-of select="$name"/></xsl:message>-->
317
                      <xsl:sequence select="f:getTypeParamTypes($type)"/>
318
                    </xsl:if>
319
                  </property>
320
                  <xsl:if test="$tokens = 'get;'">
321
                    <get />
322
                  </xsl:if>
323
                  <xsl:if test="$tokens = 'set;'">
324
                    <set />
325
                  </xsl:if>
326
                </xsl:otherwise>
327
              </xsl:choose>
328
            </xsl:when>
329
          </xsl:choose>
330
        </xsl:for-each>
331
      </xsl:for-each>
332
    </package>  
333
  </xsl:function>
334

    
335
  <xsl:function name="f:group" as="element(package)">
336
    <xsl:param name="in" as="element(package)"/>
337
    <package>
338
      <xsl:copy-of select="$in/@*"/>
339
      <xsl:for-each-group select="$in//using" group-by="@class">
340
        <xsl:sort select="@class"/>
341
        <xsl:copy-of select="current-group()[1]"/>
342
      </xsl:for-each-group>
343
      <!-- ouput JType shortnames here -->
344
      <xsl:for-each-group select="$in/*" group-starting-with="class|interface|enum">
345
        <xsl:copy>
346
          <xsl:copy-of select="@*"/>
347
          <xsl:copy-of select="type"/>
348
          <xsl:apply-templates select="remove(current-group(), 1)" mode="refine">
349
            <xsl:with-param name="type" select="current-group()[1]/@name"/>
350
          </xsl:apply-templates>
351
        </xsl:copy>
352
      </xsl:for-each-group>
353
    </package>
354
  </xsl:function>
355
  
356
  <xsl:function name="f:getTypeParams" as="xs:string*">
357
    <xsl:param name="genericType" as="xs:string"/>
358
    <!-- This may be a full generic type string, or just the part of the string with the type parameters -->
359
    <!-- Now only used for type parameters for generic methods -->
360
    <xsl:sequence select="substring-after($genericType, '&lt;') => substring-before('&gt;') => tokenize(',', 'q')"/>
361
  </xsl:function>
362
  
363
  <xsl:function name="f:getTypeParamTypes" as="element(type)*">
364
    <xsl:param name="genericType" as="xs:string"/>
365
    <!-- This may be a full generic type string, or just the part of the string with the type parameters -->
366
    <!-- Also handles covariant|contravariant types, i.e. keywords out|in, e.g. IXdmEnumerator<out XdmItem> -->
367
    <xsl:variable name="typeParams"  as="xs:string*"
368
      select="substring-after($genericType, '&lt;') => substring-before('&gt;') => tokenize(',', 'q')"/>
369
    <xsl:for-each select="$typeParams">
370
      <xsl:choose>
371
        <xsl:when test="starts-with(., 'out ')">
372
          <type type="{substring-after(., 'out ')}" extendby="out"/>
373
        </xsl:when>
374
        <xsl:when test="starts-with(., 'in ')">
375
          <type type="{substring-after(., 'in ')}" super="in"/>
376
        </xsl:when>
377
        <xsl:otherwise>
378
          <type type="{.}"/>
379
        </xsl:otherwise>
380
      </xsl:choose>
381
    </xsl:for-each>
382
  </xsl:function>
383

    
384
  <xsl:template match="*" mode="refine">
385
    <xsl:copy-of select="."/>
386
  </xsl:template>
387
  
388
  <xsl:template match="using" mode="refine"/>
389

    
390
  <xsl:template match="method-or-constructor" mode="refine">
391
    <xsl:param name="type"/>
392
    <xsl:element name="{if ($type=@name) then 'constructor' else 'method'}">
393
      <xsl:copy-of select="@*|*"/>
394
    </xsl:element>
395
  </xsl:template>
396
        
397
</xsl:stylesheet> 
398
   
399
 
(3-3/7)