The simple fact base DSL is a very simply language for defining program elements and facts in a text file rather then using a language adapter. It comes with an Xtext generated editor and a reader for creating actual refacola program elements and facts.
The fact base which is usually created by a special manually written language adapter, such as the EiffelInfoReader, can be defined in a simple text file. The format is pretty simple as you can see from its grammar:
FactBase: name=ID "{" ( Element |FactDef)* "}"; Element: kind=ID name=ID (Attribute)* ";" ; Attribute: StringAttr | ReferenceAttr | EnumAttr; StringAttr: propName=ID value=STRING; ReferenceAttr: propName=ID value=[Element]; EnumAttr: propName=ID "#" value=ID; FactDef: factName=ID "(" Arg "," Arg ("," Arg)* ")" ";"; Arg: ElementRef | Index; ElementRef: ref=[Element]; Index: "@" value=INT;
That is, the fact base consists of elements and fact definitions.
An element has a kind, such as "Class" or "TypeReference". These kinds are language specific, but since the fact base DLS has no dependencies to any concrete language (due to simplicity) you have to manually ensure the kind actually exist. Element have also a name, which is used within the fact base to reference the element.
An attribute has a name and a value, again you have to manually ensure the property actually exist for the given kind. There exist two kind of attributes: Simple string attributes (e.g., for identifiers), and references to elements. Note that these references link to the element defined in the fact base, and they do not imply new elements (for references) to be created.
Facts have a name, again you have to manually ensure the fact/query actually exist. The arguments of facts are either references to program elements or index values.
The following snippet shows a very simple fact base:
Sample1 { Class B identifier "B"; Class A identifier "A"; Feature A_foo identifier "foo" location A; has(A, A_foo); TypeReference ref_A1 identifier "A" location A; parameterType(A_foo, ref_A1, @0); Feature A_bar identifier "bar" location A; has(A, A_bar); TypeReference ref_B1 identifier "B" location A; parameterType(A_bar, ref_B1, @0); }
Note that the fact "parameterType" requires a type reference. This type reference has to be defined as a program element as well!
The fact base DSL comes with a syntax aware editor. It provides content assist for all references and also for kinds, properties, and fact names. The proposed kinds, properties, and fact names are derived from all used names within the fact base and do not reflect the actual language definition.
When testing constraints for an arbitrary language, usually a special parser (IProgramInfoProvider) is used providing the program elements and facts. During development, not only the constraints but also the parser are likely to be changed. When a test fails, it is then not always clear whether the constraint set is buggy, or if it is the parser. In order to avoid this ambiguity, it is possible to write out the program elements and facts to a fact base, using the fact base file format even if a different reader or parser has been used to create the program elements and facts in the first place. By comparing the fact base output with elder (working) versions, it is probably easier to identify existing problems.
The fact base writer writes the program elements and facts using the grammar described above. As elements are required to have a unique name, and program elements do not necessarily have name, this information has to be derived. There are several strategies for computing a name of an element:
The main idea of fact base definitions is to test special refacola features, without relying on a concrete language adapter, which may not be available or does not provide you with all necessary information. So, you probably want to use the face base with a resource test. You have to set up the test as follows:
programInfoProviderClass=de.feu.ps.refacola.factbase.FactBaseReader programInfoProviderClass.factory=de.feu.ps.refacola.lang.simplesample.SimpleSampleFactory testProgramFile=in/simple.factbase
The fact base writer can be activated and configured with the following test properties: If test property "factbase.write" is set to true, the fact base, i.e. all elements and facts, are written to an output file using the factbase file format (regardless of the initial reader).
The format can be configured with these properties: