Changes between Version 12 and Version 13 of SemanticQuery


Ignore:
Timestamp:
Mar 14, 2012, 1:23:43 PM (13 years ago)
Author:
manualwiki
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SemanticQuery

    v12 v13  
    33A semantic query language was designed to query syntactic and semantic information about Erlang programs. The language concepts are defined according to the semantic units and relationships of the Erlang language, e.g. functions and function calls, records and their usage, etc.  
    44 
    5 The main elements of the language are the '''entities''': module, function, variable, etc. Each entity has a set of selectors and properties. A '''selector''' selects a set of entities that meet the given requirements. A '''property''' describes some properties of an entity type. It is also possible to filter entities based on the properties. A '''filter''' is a boolean expression to select a subset of entities. We can build filters by using properties with boolean values, valid Erlang comparisons, logical operators or embedded queries. 
     5The main elements of the language are the '''entities''': module, function, variable, etc. Each entity has a set of selectors and properties. A '''selector''' selects a set of entities that meet the given requirements. A '''property''' describes some properties of an entity type. It is also possible to filter entities based on the properties. A '''filter''' is a boolean expression to select a subset of entities. We can build filters by using properties with boolean values, valid Erlang comparisons, logical operators or embedded queries. For usage examples, see: SemanticQuery/QueryExamples. 
    66 
    77== Formal syntax of the language == 
     
    248248 
    249249== Examples == 
    250  
    251 === Basic queries === 
    252 As you can read in the introduction, in this language we build difficult queries from lot of very simple queries. Here are some examples for simple ones: 
    253  
    254 {{{ 
    255 @fun.refs 
    256 }}} 
    257 Returns a list of expressions which call the pointed function. 
    258  
    259 {{{ 
    260 @file.funs.calls 
    261 }}} 
    262 Returns all function calls from current module group by the module's own functions. 
    263  
    264 {{{ 
    265 @file.funs[arity==3] 
    266 }}} 
    267 Returns all functions which have 3 arguments. 
    268  
    269 === Advanced queries === 
    270 Let's see some useful queries: 
    271  
    272 {{{ 
    273 @file.funs.vars[name=="Expl"] 
    274 }}} 
    275 Returns all functions which have a variable named "Expl". It useful when we want to know which functions use variables with same name. 
    276  
    277 {{{ 
    278 mods[name=="io"].funs[name==format].refs 
    279 }}} 
    280 Returns all io:format calls, this query is very useful when you have finished your software, and you want to find all debug messages. 
    281  
    282 {{{ 
    283 @expr.origin 
    284 }}} 
    285 For example we stand in a variable, and run this query, we get information about the variable gets its value from where. This functionality uses [wiki:DataFlow data-flow analysis]. 
    286  
    287 {{{ 
    288 @fun.refs.origin 
    289 }}} 
    290 Returns information about the function gets its return value from where and how its calculated. 
    291  
    292 === Checking coding convensions === 
    293  
    294 In !RefactorErl, [MetricQuery#Definedmetrics metrics] can be applied to modules or to functions. Modules are equivalent to {{{file}}} entities in the semantic query language, and functions are equivalent to {{{function}}} entities. We can say that a metric is a kind of property belongs to a {{{file}}} or {{{function}}} entity, so we can simply add the proper metrics to the properties of entities. 
    295  
    296 Usually we have some coding conventions applied to our modules or functions. With our extended semantic query language we can check these conventions, and filter improper modules or functions. Hereinafter we present some design rules and some metrics to check these rules. 
    297  
    298 ''' Rule1. A module should not contain more then 400 lines.''' 
    299  
    300 When we would like to filter modules containing more than 400 effective lines of code, we have to load our modules to !RefactorErl system, and enter the following query: 
    301 {{{ 
    302 modules[line_of_code > 400] 
    303 }}} 
    304 In the result we will find our too long modules. 
    305  
    306 ''' Rule2. A function should not contain more then 15 to 20 lines.''' 
    307  
    308 When we would like to check, which functions do not fulfil this convention in our modules loaded into the !RefactorErl database, we use the following query: 
    309 {{{ 
    310 modules.funs[line_of_code > 20] 
    311 }}} 
    312  
    313 ''' Rule3. Use at most two level of nesting, do not write deeply nested code.''' It is achieved by dividing the code into shorter functions. 
    314  
    315 With one of our metrics we can count the nesting level of case expressions, so we can filter functions with more than two maximum depth of cases. In this example, we would like to get the result just from our actual module. 
    316 {{{ 
    317 @file.funs[max_depth_of_cases > 2] 
    318 }}} 
    319  
    320 If we just would like to know, whether all of the functions fulfil this convention or not, we can simply query the maximum nesting level of cases in the whole module. If this value is more than two, there is at least one function containing deeply nested cases. 
    321 {{{ 
    322 @file.max_depth_of_cases 
    323 }}} 
    324  
    325 At least, let's filter modules containing functions with too deeply nested cases. 
    326 {{{ 
    327 mods[max_depth_of_cases > 2] 
    328 }}} 
    329  
    330 ''' Rule4. Use no more than 80 characters on a line.''' 
    331  
    332 We can filter all of the functions, which contains lines with more than 80 characters with the following query: 
    333 {{{ 
    334 mods.funs[max_length_of_line > 80] 
    335 }}} 
    336  
    337 ''' Rule5. Use space after commas.''' 
    338  
    339 We have a metric which returns with the number of cases when we do not fulfil this convention. When a modul or a function breaks this rule, the result of the metric will be more, then 0. 
    340  
    341 Filter functions containing at least one case when whitespace misses after 
    342 a comma: 
    343 {{{ 
    344 mods.funs[no_space_after_comma > 0] 
    345 }}} 
    346  
    347 ''' Rule6. Every recursive function should tail recursive.''' 
    348  
    349 Tail recursion means that we have no recursive call (either direct or indirect) in our function, just in the last expression. Filter functions that recursive, but not tail recursive: 
    350 {{{ 
    351 mods.funs[is_tail_recursive == non_tail_rec] 
    352 }}} 
    353  
    354  
    355  
     250Some basic and advanced query example, and queries for checking coding conventions can be found [SemanticQuery/QueryExamples here]. 
     251 
     252