When displaying information to the user, Semmle client applications like Semmle Studio, Semmle Mend or Project Insight need to be able to extract location information from the results of a query. In order to do this, all QL classes which can provide location information should do this by using one of the following mechanisms:
The list is in priority order, so that the first available mechanism is used.
Since QL is a relational language, there is nothing to enforce that each entity of a QL class is mapped to precisely one location. This is the responsibility of the designer of the library (or the populator, in the case of the third option below). If entities are assigned no location at all, query results may surprisingly disappear in some client applications. If multiple locations are assigned, they may be duplicated.
A custom URL can be provided by defining a QL predicate returning
string with the name
getURL – note that capitalisation matters, and no arguments are allowed. For example:
The following types of URL are available:
- HTTP URLs are supported in the Project Insight dashboard (and possibly other client applications). For an example, see the above code snippet.
- File URLs are the most common type of URL for code defects or metrics. The schema is
file://, which is followed by the absolute path to a file, followed (optionally) by three or four numbers separated by colons. If there are three numbers, they are taken to mean the start line number, character offset and character length of the location respectively; if there are four, they denote start line, start column, end line and end column. Both line and column numbers are 1-based. By convention, the whole file's location is either denoted by a
file://URL without trailing numbers, or by trailing numbers of 0. A few examples:
file:///home/semmle/odasa/src/my/file.cdenotes the entire file at the given path.
file://C:/Users/Odasa/src/my/file.c:0:0:0:0does the same.
file:///home/semmle/odasa/src/my/file.c:1:1:2:1denotes the location that starts at the beginning of the file and extends to the first character of the second line (the range is inclusive).
file:///home/semmle/odasa/src/my/file.c:1:0:1:0is taken, by convention, to denote the entire first line of the file.
- Folder URLs can be useful, for example to provide folder-level metrics. They may use a file URL, for example
, but they may also start with a scheme of
folder://, and no trailing numbers, for example
- Relative file URLs are like normal file URLs, but start with the scheme
relative://. They are typically only meaningful in the context of a particular snapshot, and are taken to be implicitly prefixed by the snapshot's source location. Note that, in particular, the relative URL for a file will stay constant regardless of where the snapshot is analysed. It is often most convenient to produce these URLs as input when importing external information; selecting one from a QL class would be unusual, and client applications may not handle it appropriately.
Providing location information
getURL() member predicate is defined, a QL class is checked for the presence of a member predicate called
hasLocationInfo(..). This can be understood as a convenient way of providing file URLs (see above) without constructing the long URL string in QL.
hasLocationInfo(..) should be a predicate, its first column must be
string-typed (it corresponds to the "path" portion of a file URL), and it must have an additional 3 or 4
int-typed columns, which are interpreted like a trailing group of three or four numbers on a file URL.
For example, let us imagine that the populated locations for methods extend from the first character of the method name to the closing curly brace of the method body, and we want to "fix" them in QL to ensure that only the method name is selected. The following code shows two ways of achieving this:
Using populated location information
Finally, if the above two predicates fail, Semmle client applications will attempt to call a predicate called
getLocation() with no parameters, and try to apply one of the above two predicates to the result. This allows Semmle's tools to put certain locations into the database, assigning them identifiers, and have them picked up.
By convention, the return value of the
getLocation() predicate should be a QL class called
Location, and it should define a version of
getURL(), though the former is preferable). If the
Location class does not provide either of these member predicates, then no location information will be available.
The toString() predicate
All classes must provide a
string toString() member predicate. The compiler will complain if you don't. The same uniqueness warning as for locations applies.