| 267 | |
| 268 | When the groupby option is used for queries with set operators, the interpretation depends on the type of the used set operators. |
| 269 | |
| 270 | If the operands of the outermost set operation in the query are semantic queries themselves, the groupby option is passed to the execution of the operands. So in the following query |
| 271 | {{{ |
| 272 | ri:q("(mods.funs.vars.name U mods.funs.loc)", [{groupby, 2}]). |
| 273 | }}} |
| 274 | the results are grouped by functions, the second selector of each sub-query. |
| 275 | |
| 276 | When the grouping of a set operator's sub-queries do not match(different selector types, or at least one of them is not grouped), the results will be grouped by files; as in the following query: |
| 277 | {{{ |
| 278 | ri:q("(mods.funs.vars.name U mods.funs.clause.loc)", [{groupby, 3}]). |
| 279 | }}} |
| 280 | As far as grouping is concerned, other set operators(e.g. a set operator between series of selectors) in a query are regarded as one unit. The numbering of the elements as used by the groupby option are incremented by one after the set operator, as if it was a single selector of the type resulting from any of the operands. |
| 281 | |
| 282 | ''Example:'' |
| 283 | {{{ |
| 284 | ri:q("mods(.funs[name ~ \"filter\"].calls U .exports[name ~ \"drop\"]).params.vars", [{groupby, 2}]). |
| 285 | }}} |
| 286 | So the query above is grouped by functions, the type of the results of the set operator. |
| 287 | |
| 288 | == Analysing "-type" and "-spec" related informations == |
| 289 | |
| 290 | Erlang is dynamically typed, but it provides notations for types in the Erlang syntax. Although these do not affect the operation of the compiled code, it is generally a good practice to utilize them for type checking and other purposes, like doc generation. Our tool analyzes and stores "-type", "-opaque", "-export_type", "-spec" attributes and the types of record fields. These information can be conveniently accessed/used and comprehended via semantic queries. |
| 291 | |
| 292 | === Returned values for new internal types in sq: === |
| 293 | As it can be seen in the description of [SemanticQuery/Components Available components], for the practical use of analyzed type informations, new internal types have been introduced for semantic queries. When a query isn't continued with other selectors to reach conventional types, it might not be obvious what the results would be. In case of our text-based and graphical interfaces, the format of the shown result for each of these entities can be found in their corresponding pages: [SemanticQuery/SpecEntity Spec], [SemanticQuery/SpecParamEntity Spec param], [SemanticQuery/TypeEntity Type]. |
| 294 | |
| 295 | Our scriptable interface, along with the textual representations, also provides the unique entities of the stored type informations, which might be used to differentiate between results even when their formatted values are the same. |
| 296 | |
| 297 | {{{ |
| 298 | ris:q("mods.specs.params.type.params"). |
| 299 | {rich,"a:prp_user/2\n Key\n Val\nb:prp_user/2\n Key\n Val\nc:prp_user/2\n Key\n Val\n", |
| 300 | [{entity,{'$gn',typexp,151}}, |
| 301 | {entity,{'$gn',typexp,152}}, |
| 302 | {entity,{'$gn',typexp,296}}, |
| 303 | {entity,{'$gn',typexp,297}}, |
| 304 | {entity,{'$gn',typexp,439}}, |
| 305 | {entity,{'$gn',typexp,440}}]} |
| 306 | }}} |
| 307 | |
| 308 | === Detailed review of non-trivial selectors: === |
| 309 | |
| 310 | During the specification we have tried our best to keep things simple in the perspective of usability. This meant that for example we would not differentiate between namedtypes(user-defined, built-in) and type expressions. In some cases this have resulted in rather complex specifications. Under normal circumstances, the different behaviors should be intuitively evident and would not cause any surprise. For the newly introduced entities, information about these selectors can be found on their respective pages: [SemanticQuery/SpecEntity Spec], [SemanticQuery/SpecParamEntity Spec param], [SemanticQuery/TypeEntity Type]. For others they are listed here: |
| 311 | |
| 312 | ==== File.typerefs: ==== |
| 313 | This selector returns all types referenced in the file. It does not return type expressions, but it returns all other types(even built-in types or ones which have been defined in an other file) that have been referenced in "-spec", "-type", "-opaque" attributes or record definitions. |
| 314 | {{{ |
| 315 | ri:q("mods.typerefs"). |
| 316 | a.erl |
| 317 | erlang:atom/0 |
| 318 | a:prp_user/2 |
| 319 | }}} |
| 320 | |
| 321 | ==== Function.returntype(, Spec.returntype): ==== |
| 322 | Returns types or type expressions present as the return-type of the function's specs. It does not split union types, but please note that specs can be overloaded so even functions with only one clause can have multiple values. (Single-atom type expressions are filtered.) |
| 323 | {{{ |
| 324 | ri:q("mods.funs.returntypes"). |
| 325 | a:g/2 |
| 326 | erlang:atom/0 |
| 327 | }}} |
| 328 | |
| 329 | === Limitations: === |
| 330 | - For performance and readability reasons, type-expressions consisting of a single atom(e.g., bool, int, 'error') are filtered from results. This means, without re-parsing the textual representations, the results can not be used perform reliable type checking or comparison for functions. (We believe, including such simple expressions in results for an ordinarily large code-base would undermine the main goal of these features, which is providing an easy way for understanding type informations and their relation.) |
| 331 | - As of now, "@type" and "@spec" declarations are not analyzed. |
| 332 | - "-spec" attributes are not mapped to function clauses, but only to their functions. |