MASARYK U N I V E R S I T Y FACULTY OF INFORMATICS Unite client for Visual Studio Code Bachelor's Thesis FILIP NOVÁČEK Brno, Fall 2022 MASARYK U N I V E R S I T Y FACULTY OF INFORMATICS Unite client for Visual Studio Code Bachelor's Thesis FILIP NOVÁČEK Advisor: doc. Ing. RNDr. Barbora Buhnova, Ph.D. Department of Computer Systems and Communications Brno, Fall 2022 Declaration Hereby I declare that this paper is my original authorial work, which I have worked out on my own. A l l sources, references, and literature used or excerpted during elaboration of this work are properly cited and listed in complete reference to the due source. Filip Nováček Advisor: doc. Ing. RNDr. Barbora Búhnová, Ph.D. iii Acknowledgements I would like to thank my advisor doc. Ing. RNDr. Barbora Buhnova, Ph.D and my consultant Ing. Jan Fiedor Ph.D for their advice and aid in writing this thesis. I would also like to thank my family for their support. iv Abstract The goal of this thesis was to create a client for Unite integrated in Visual Studio Code. Unite is an adapter providing code analysis as an OSLC-compliant service. The client shall be able to request code analysis by Unite running on a remote server and visualize the results of the analysis directly in the Visual Studio Code IDE. The implementation focuses on compliance with OSLC and the tool's independence of OSLC domains, which makes it versatile, and compatible with other OSLC-compliant services. Keywords OSLC, Visual Studio Code, Unite, RDF, Linked Data v Contents 1 Introduciton 1 2 OSLC 2 2.1 OSLC Idea 2 2.1.1 Lifecycle Management 2 2.2 OSLC Structure 2 2.3 RDF 3 2.3.1 URI 3 2.3.2 Literals 4 2.3.3 X M L 4 3 Important Technologies 7 3.1 Unite 7 3.2 Facebook Infer 7 3.3 Visual Studio Code 8 4 Analysis and Design 9 4.1 Requirements 9 4.1.1 Visual Studio Code Integration 10 4.1.2 OSLC-compliant Service 10 4.1.3 OSLC-compliant Interaction 11 4.2 Modules 11 4.2.1 Structure 12 4.2.2 Oslcjs 12 4.2.3 UnicJS 15 4.2.4 UnicVS 16 4.3 Client-Domain Separation 16 5 Implementation 17 5.1 Oslcjs 17 5.1.1 Domain Definition 17 5.1.2 Deserialize 20 5.1.3 Validation 21 5.2 UnicJS 22 5.2.1 Zip 22 vi 5.2.2 Asynchrnous GET and POST 22 5.2.3 Transient Errors 24 5.3 UnicVS 24 5.3.1 Input and Output 24 5.3.2 Configuration 25 5.3.3 Usage 27 6 Evaluation 30 6.1 Functional Requirements 30 6.2 Non-functional Requirements 30 6.3 User Testing 31 6.4 Future Work 31 6.4.1 Generating Class Code 31 6.4.2 Downloading Resource Specification 32 6.4.3 Graphical Output 32 7 Conclusion 33 Bibliography 34 A Source Code 36 vii List of Figures 4.1 Structure of the modules 13 5.1 UnicVS Settings UI 26 5.2 UnicVS UI - Requesting Analysis 28 5.3 UnicVS UI - Analysis in progress 29 5.4 UnicVS UI - Analysis finished 29 viii 1 Introduciton Unite [1] is an adapter that allows execution of static code analysis tools on a remote server. Currently, a client for Unite exists integrated into the Eclypse Lyo IDE. However, there is no client for Visual Studio Code. Many of the developers from Honeywell, MUNI's industrial partner involved in the development of Unite, use Visual Studio Code and expressed they would appreciate integration into it. Honeywell has also been contacted by engineers from Google, expressing similar preference. Aim of the thesis The aim of the thesis is to provide an integrated client to allow Visual Studio Code users to run code analysis using Unite on a remote server directly in the IDE. Context of the thesis This thesis has been made in cooperation with Honeywell, as a part of its effort to build OSLC infrastructure. It is connected in its efforts to the ArrowHead project [2], which works on creating an OSLC architecture for Eclypse Lyo, and whose members requested similar functionality for Visual Studio Code. Structure of the thesis Chapter 2 describes the theoretical basic principles of OSLC and the technologies used to represent it in this project, such as RDF and XML. Chapter 3 presents important technologies this tool interacts with. Chapter 4 describes the requirements and structure of the tool as well as the design choices made during its development. Chapter 5 focuses on selected implementation details and challenges. It also provides a guide on how to use the tool. Chapter 6 presents evaluation of the project and some ideas for future work. 1 2 OSLC This chapter discusses OSLC, its structure, and its representation using RDF and XML. 2.1 OSLC Idea OSLC [3] stands for Open Services for Lifecycle Collaboration. It is an open community that attempts to provide a unified format of exchanging data between tools, creating universal compatibility between any programs [3]. 2.1.1 Lifecycle Management OSLC tries to provide better integration options for different kinds of tools throughout the entire lifecycle of a project [4]. According to OSLC, in an ideal state, all data from the requirements at the beginning of a project, through development, testing, and architecture management to quality management would conform to the same format [5]. The benefit of this is that tools for all stages can interact with each other and access data directly from another product making integration easier and more scalable [6]. To meet the needs of different types of information needed in each step of the product's lifecycle, OSLC provides specifications [5] for different domains, each handling a different stage. 2.2 OSLC Structure OSLC data must comply to the specification of RDF with added constraints [3]. Because it is a specification over RDF, OSLC is in its nature abstract and has to be encoded to be stored and represented in a computer. While there are multiple formats RDF, and therefore also OSLC, can be encoded in, this tool uses the X M L format since it is also the one used by Unite. OSLC defines several domains to represent different kinds of data for different purposes as discussed in Section 2.1.1. These include 2 2. OSLC for example Quality Management, Asset Management, or Change Management [7, 3]. Unite uses the Automation domain so this will be the one this thesis focuses on the most. The basic element of OSLC data is an OSLC Resource. This would for example represent a request for analysis by Unite. Each of the resources has a type, which in this example would be Automation Request. The type of the resource then specifies its properties. These would include time the request was created, whether the request has been completed, or its input parameters. 2.3 RDF RDF (Resource Description Framework) is a specification of data which aims to be both readable by a human and easily interpretable by a machine [8]. It tries to achieve this by linking small pieces of data together into a large unified network. RDF data is a large set of triples, each of which specifies the relation between two entities [9]. In this sense, an entity can be any real object RDF is trying to represent or a property of such an object. Each data entry of RDF is a triple of three elements: Subject, predicate and object [10]. Subject is an entity we are interested in. Predicate is a relationship and object is an entity, which the first entity has the relationship to [11]. For example, the information that "Alice is Bob's mother" would be represented by a triple with a triple which would have Alice as the subject, motherhood as the predicate, and Bob as the object. Similarly "Bob is 22 years old" would be represented as a triple with Bob as the subject, age as the predicate, and 22 years as the object. 2.3.1 URI When encoding the data, each of the entities needs to be represented in a way usable by a computer. For RDF to work as intended, each entity has to be represented by a unique identifier. This way any entity can refer to any other entity and a global network of data is created. To achieve this, RDF uses Universal Resource Identifiers or URIs for 3 2. OSLC short. Each URI is a unique string representing a single entity. To continue the example, using URIs, "Alice is Bob's mother" would now be represented by a triple with "http://example.com/people/Alice" as subject, "http://example.com/relationships/mother" as predicate, and "http://example.com/people/Bob" as object, where "http://example.com/people/Alice" is now a URI representing the specific human, named Alice, this data is about. Any other properties of this Alice would then use the same URI in the triple to present more information about her. 2.3.2 Literals In some cases, a URI is not necessary as the entity represented is already uniquely identified by itself. This applies for example to numbers or names. In such case, RDF uses literals to represent these entities [9]. For example, the information that "Bob is 22 years old" would use Bob's URI as a subject and the URI of age as the predicate but a literal of 22 as the object. 2.3.3 XML One of the formats to represent RDF data in a computer uses X M L . X M L stands for Extensible Markup Language and it is a simple format used to represent different types of data. It uses plain text and tags within it, which mark certain parts of it to define sections [12]. While it has "markup language" in its name, it is not a true markup language. This is because it defines the structure and syntax of the markup, but not the definitions for each tag. This makes it very versatile as each usage of X M L can define the tags for its specific purposes. RDF defines a set of tags to represent RDF data by X M L [13]. X M L uses a pair tag with an rdf:about attribute to represent the entity, a custom tag to represent the predicate with another rdf:about attribute to represent the object. Listing 2.1 presents a simple example of the information "Alice is a mother of Bob" and "Bob is a 25 years old builder" encoded in RDF using XML. 4 2. OSLC Listing 2.1: RDF+XML simple example < r d f : R D F x m l n s : r d f = " h t t p : / / w w w . w 3 . o r g / l 9 9 9 / 0 2 / 2 2 - r d f - s y n t a x - n s # " x m l n s : r e l a t i o n s = " h t t p : / / w w w . e x a m p l e . c o m / r e l a t i o n * " x m l n s : p r o p e r t i e s = " h t t p : / / w w w . e x a m p l e . c o m / p r o p e r t y * " < r d f : D e s c r i p t i o n r d f : a b o u t = " h t t p : / / w w w . e x a m p l e . c o m / p e o p l e / A l i c e " > < r e l a t i o n s : m o t h e r r d f : r e s o u r c e = " h t t p : / / w w w . e x a m p l e . c o m / p e o p l e / B o b " > < / r d f : D e s c r i p t i o n > < r d f d e s c r i p t i o n r d f : a b o u t = " h t t p : / / w w w . e x a m p l e . c o m / p e o p l e / B o b " > < p r o p e r t i e s : a g e > 25 < / p r o p e r t i e s : a g e > < / r d f : D e s c r i p t i o n > < r d f d e s c r i p t i o n r d f : a b o u t = " h t t p : / / w w w . e x a m p l e . c o m / p e o p l e / B o b " > < r e l a t i o n s : o c c u p a t i o n r d f : r e s o u r c e = " h t t p : / / w w w . e x a m p l e . c o m / o c c u p a t i o n / B u i l d e r " > < / r d f : D e s c r i p t i o n > < / r d f : R D F > To make the data more readable by humans, RDF+XML also allows a simplified syntax in which multiple relationships of the same entity are defined under one tag. The resulting encoding then looks more like an object with properties which makes it more intuitive to understand. Listing 2.2 presents an example of the same information as Listing 2.1 in the simplified syntax. Listing 2.2: Rdf+XML shortened example < r d f : R D F x m l n s : r d f = " h t t p : / / w w w . w 3 . o r g / l 9 9 9 / 0 2 / 2 2 - r d f - s y n t a x - n s # " x m l n s : r e l a t i o n s = " h t t p : / / w w w . e x a m p l e . c o m / r e l a t i o n * " x m l n s : p r o p e r t i e s = " h t t p : / / w w w . e x a m p l e . c o m / p r o p e r t y * " > < r d f d e s c r i p t i o n r d f : a b o u t = " h t t p : / / w w w . e x a m p l e . c o m / p e o p l e / A l i c e " > < r e l a t i o n s : m o t h e r > < r d f d e s c r i p t i o n r d f : a b o u t = " h t t p : / / w w w . e x a m p l e . c o m / p e o p l e / B o b " > < p r o p e r t i e s : a g e > 22 < / p r o p e r t i e s : a g e > < r e l a t i o n s : o c c u p a t i o n r d f : r e s o u r c e = " h t t p : / / w w w . e x a m p l e . c o m / o c c u p a t i o n s / B u i l d e r " > < / r d f d e s c r i p t i o n > < / r e l a t i o n s : m o t h e r > < / r d f : R D F > OSLC in RDF+XML When representing OSLC data in RDF, each OSLC resource is considered to be one entity and so is each of that resource's properties. When the value of a property is another OSLC resource, 5 2. OSLC it is represented by its U R L Otherwise, the value of the property is represented by a literal. Some resources are completely defined only by their relations to other resources. For example, an input parameter resource stores a name and a value of a parameter of another resource. Since such resources are never referenced without relation to their linked resource, in these cases OSLC omits the U R l and uses the simplified X M L syntax to describe the resource. Listing 2.3 shows an example of such description. Listing 2.3: RDF+XML OSLC example < r d f : R D F x m l n s : r d f = " h t t p : / / w w w . w 3 . o r g / l 9 9 9 / 0 2 / 2 2 - r d f - s y n t a x - n s # " x m l n s : d c t e r m s = " h t t p : / / p u r l . o r g / d c / t e r m s / " x m l n s : o s l c = " h t t p : / / o p e n - s e r v i c e s . n e t / n s / c o r e # " x m l n s : o s l c _ a u t o = " h t t p : / / o p e n - s e r v i c e s . n e t / n s / a u t o#" > < o s l c _ a u t o : A u t o m a t i o n R e q u e s t > < o s l c _ a u t o : i n p u t P a r a m e t e r > < o s l c _ a u t o : P a r a m e t e r I n s t a n c e > < o s l c : n a m e > b u i l d C o m m a n d < / o s l c : n a m e > < r d f : v a l u e > g c c - g T e s t E c h o P r o g r a m . c p p - o m y _ e c h o < / r d f : v a l u e > < / o s l c _ a u t o : P a r a m e t e r I n s t a n c e > < / o s l c _ a u t o : i n p u t P a r a m e t e r > < o s l c _ a u t o : i n p u t P a r a m e t e r > < o s l c _ a u t o : P a r a m e t e r I n s t a n c e > < o s l c : n a m e > l a u n c h C o m m a n d < / o s l c : n a m e > < r d f : v a l u e > . / m y _ e c h o < / r d f : v a l u e > < / o s l c _ a u t o : P a r a m e t e r I n s t a n c e > < / o s l c _ a u t o : i n p u t P a r a m e t e r > < / o s l c _ a u t o : A u t o m a t i o n R e q u e s t > < / r d f : R D F > 6 3 Important Technologies This chapter summarizes three technologies this tool needs to interact with. It is Unite, which provides the analysis, Facebook Infer, used for evaluation of the tool, and Visual Studio Code, which this tool provides the client integration to. 3.1 Unite Unite is an acronym for UNIversal analysis adapTEr. It is a tool that allows its user to turn any command line tool performing a static analysis of code into a remote server service. Requests for analysis can be sent to Unite using the automation domain of OSLC specification [14]. The communication is done through REST requests using RDF+XML to encode the OSLC data. The entire communication with Unite to perform one analysis can be modeled in four steps: 1. Register SUT, 2. Check SUT registration, 3. Perform analysis, 4. Get analysis result. In step one, Unite is given the data and begins registering it. In this step, it may also compile the code if the analysis tool requires it. In step two the client polls the server to find out whether the registration has been completed and step three can start. In step three Unite performs analysis on the code and in step four the client polls the server to find out whether the analysis is finished and collects the result data. This process defines the requirements presented in Section 4.1 3.2 Facebook Infer Infer [15] is a static code analysis tool developed by Facebook. Currently, it is able to analyze Java, C, and Objective-C. It is used by 7 3- IMPORTANT TECHNOLOGIES Facebook to analyze changes in the code of their apps, but it is also available to the public for free. 3.3 Visual Studio Code Visual Studio Code [16] is an Integrated Development Environment. There is no specific language it was designed for. Instead, it allows the integration of many programming languages through the use of extensions [17]. Extensions are the main feature of Visual Studio Code. They allow developers to modify the IDE to suit their needs. They can provide support for different languages, add visual themes, or provide integration of external tools. Visual Studio Code allows the creation of extensions by providing a JavaScript API [17]. It also sets up guidelines for best practices for creating extensions [18] defining the correct usage of UI elements and functions the creator of an extension should adhere to, to maintain a unified look and functionality expected by Visual Studio Code users. 8 4 Analysis and Design This chapter describes the design choices made during the development of the tool. Section 4.1 focuses on requirements for the tool and how this tool was designed to satisfy those requirements. Section 4.2 goes on to describe the division of the project into modules and the function and design of each of those modules. 4.1 Requirements This section discusses the requirements of the tool and the ways the design of the tool aims to satisfy those requirements. These are the requirements the integrated client must satisfy: 1. The client has to be able to collect the project data from Visual Studio Code. 2. The client has to be able to send the data to a remote server for analysis. 3. The client has to be able to validate whether the data was correctly delivered. 4. The client has to be able to remotely run the analysis on previously delivered data. 5. The client has to be able to detect that the analysis was completed. 6. The client has to be able to download the resulting data. 7. The client has to view the result to the user in Visual Studio Code. 8. The analysis must be provided as an OSLC-compliant service. 9. The interaction with remote analysis must be OSLC-compliant. 9 4. ANALYSIS A N D DESIGN 4.1.1 Visual Studio Code Integration Extension The tool is created as an extension to Visual Studio Code. This allows the tool to add elements to the UI of Visual Studio Code and provides a smooth integration into the IDE. As a result, the user does not have to leave the IDE to work with the tool. Language When deciding on the language to write the tool in, several options were considered. The three most promising ones were Java, Python, and JavaScript. Writing the tool in Java would mean less work as there is already a finished Java implementation for Eclypse Lyo. The advantage of Python is its popularity. Many libraries for Python exist, making development easier. Furthermore, unlike JavaScript, it supports decorators, which would simplify the definition of OSLC resource objects. It would also have greater potential for reusing of the code for other applications. The main advantage of JavaScript is that Visual Studio Code provides a JavaScript API [17] for creating extensions. While there are no APIs for other languages, there are libraries that allow creating extensions in other languages and translating them to JavaScript [19] so writing the tool in Python would not be impossible. However, making the extension directly in JavaScript means one less dependency is required. Furthermore, it allows for core parts of the tool to be reused to make integration for browsers and other JavaScript projects. Because of that, JavaScript was chosen as the language to develop the tool in. 4.1.2 OSLC-compliant Service Unite As mentioned in Chapter 1, Unite is an adapter allowing its users to run analysis on a remote server as an OSLC-compliant service. This means that in the future, any adapters which provide analysis as an OSLC-compliant service should be compatible with this tool. Furthermore, the tool should only need small modifications to be compatible with adapters providing other OSLC-compliant services. 10 4. ANALYSIS A N D DESIGN 4.1.3 OSLC-compliant Interaction Client To provide an OSLC-compliant interaction with Unite, the tool needs to be able to send and receive OSLC data. This is achieved by using an OSLC Client - a program able to create, process, send, and receive REST requests containing RDF data. To be able to create and process the data in a convenient way, the client should also be able to represent the data in a more human-friendly form and translate the data between this form and the serialized form used in requests. A naive way to do this would be writing a code that directly parses the X M L string when receiving a response and serializes resources into strings to create requests. This option would be chosen if no other option was available. Luckily, there are other options to do this. One of them would be using a library called Oslc-client [20]. It is a library that allows the user to fetch OSLC data, and parse it into a simple object model. However, the library is very minimalistic and it ignores OSLC domains translating all resources into the same type of object, regardless of the type of the resource. This makes working with the resulting object model difficult. Furthermore, most of its functionality is provided by rdflib [21] - a library which Oslc-client requires as a dependency. This means it is more convenient for this project to make its own solution instead of using Oslc-client and to use rdflib as a dependency as well. This way the low-level string editing is avoided, but freedom in representing the objects more conveniently is retained. 4.2 Modules The functionality of this program can naturally be divided into three parts - one to handle the representation of OSLC data and the sending and receiving of the requests as described in Section 4.1.3, one to handle the actual interaction with Unite, and one to provide integration to Visual Studio Code. Because of this, the tool has been separated into three modules corresponding to these three parts. Each module is separately available as a package and they are connected through dependency. This allows developers to reuse the code for handling 11 4. ANALYSIS A N D DESIGN OSLC data and requests in their projects and to reuse the code for the client for integration to browsers or other IDEs. 4.2.1 Structure The three modules of this project have been named Oslcjs, UnicJS, and UnicVS. Oslcjs represents OSLC data in a JavaScript object structure and parses X M L requests. UnicJS creates the requests for Unite and directs the analysis, and UnicVS integrates the functionality of this project into Visual Studio Code and interacts with the user through its UI. Figure 4.1 shows a model of the structure of this tool and the communication between its modules . Note that within one run of the program, UnicVS only requests the analysis from UnicJS once, but UnicJS creates one request per step of the analysis, which is then processed by Oslcjs and Unite. 4.2.2 Oslcjs The base-level library, which all the others require, has been named Oslcjs. This library includes all the functionality needed to represent OSLC data in a usable form, serializing it into RDF and parsing RDF data into this representation. Rdflib Oslcjs requires Rdflib as a dependency. Rdflib [21] is a library that allows its user to parse RDF data encoded in X M L to triples and to encode these triples into X M L . The inner representation is a set of triples. The elements of each of the triples are instances of either of three classes: NamedNode, BlankNode, and Literal. These nodes are used to represent resources with URIs, resources without URIs, and literals, respectively. Each of the triples then represents one RDF statement. This way it is possible to work with RDF data without having to manually edit the X M L string. However, this representation is still very unwieldy and not practical for OSLC. That is why Oslcjs uses its own representation of the data, which is more usable. Object model Oslcjs represents each resource as an instance of a JavaScript Object. Each type of resource required by the tool is represented by a separate class. Attributes of the class then represent 12 r UnicVS User Interaction Visual Studio Code Integration 4. ANALYSIS A N D DESIGN Each step r 1 Oslcjs Serializing oslc requests Parsing Unite's responses ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Rdflib XMLHttpRequest Figure 4.1: Structure of the modules relations of the resource to other resources. In the triple representation, the instance would map to subject, the attribute would map to predicate and the value of the attribute would map to object. This tree-like representation allows for a much more intuitive way to see the data and the mapping to attributes allows the user to edit the data in a familiar way. OSLCResource To make the code reusable in other projects, I decided not only to make the library support the Automation Domain needed for communication with Unite but to make it extensible so that developers can use it to define other OSLC domains. To allow 13 4. ANALYSIS A N D DESIGN simple addition of new resource types, most of the functionality of Oslcjs is provided by a class named OSLCResource from which each of the classes representing resource types inherits. OSLCResource handles serializing data to X M L and deserializing X M L data to the object model. It also handles storing metadata, which is needed for serializing and deserializing, about the resource type. Additionally, it provides functions by which a user can set up a new class to represent a new resource type and define the metadata for its attributes. Using the inheritance from OSLCResource and these functions, a user can simply define any OSLC domain they need for a project. REST Client Oslcjs also handles low-level communication with the server. It provides a simple client class with get and post functions, which use instances of the OSLCResource class as arguments. This allows the user to send get and post requests directly with their olsc resources and not worry about serialization into X M L or parsing the response into the object model as all of this is handled by the functions. The functions are mostly wrapper functions over the corresponding functions provided by the XMLHttpRequest library [22] with the addition of setting up the relevant listeners and headers, serializing the resource before sending it, and parsing the result. XMLHttpRequest XMLHttpRequest [22] is a library, which provides functionality that is already natively present in browsers to non-browser projects. This functionality is provided by an object called XMLHttpRequest. As the name suggests, this object has functions for setting up and sending an HTTP request. One of its disadvantages is that it is very wordy, meaning it requires multiple lines of code to set up a simple request. This, however, is not a problem for Oslcjs, since it needs to define its own wrapper functions for the HTTP methods, hiding the wordy setup from its user. O n the other hand, the advantage, which is freedom in specifying details of the request, is useful for Oslcjs. There are several more reasons for using this library. Firstly, it makes Oslcjs compatible with browsers, allowing reusing the code for browser projects. Moreover, it is already a dependency of rdflib, which is used by Oslcjs, so using it does not add another dependency. 14 4. ANALYSIS A N D DESIGN 4.2.3 UnicJS UnicJS is a module that handles communication with the remote analysis service. It requires Oslcjs as a dependency. UniC The tool aims to be as similar as possible to UniC - the already existing Java implementation. This will allow existing users of UniC to easily transition to this tool when using Visual Studio Code instead of Eclipse Lyo and in the future, new users can easily switch between them. Steps In communication with Unite, UnicJS has to follow the pattern outlined in Section 3.1 to successfully complete the analysis. Structure Most of the functionality of UnicJS is provided by a class called Analyser. A n instance of Analyser holds information about the analysis tool and all extra metadata needed for the communication. It also provides methods for interaction with Unite, which directly correspond to the steps from Section 3.1. Furthermore, it defines a method that performs all these steps in order. This gives the user the comfort of running one method to perform the entire analysis while also giving them the freedom to perform the individual steps if so they choose. Zip Unite accepts project data in multiple different ways, such as an url from which it downloads, or as a git repository. UnicJS uses the option to send a zip file with the project data encoded in base64 directly in the request. This has the advantage of not requiring an extra server to store the data just to upload it. It is also the least prone to failure. For this reason, UnicJS also defines a method to zip a directory and encode it to base64. This method recursively goes through the directory and uses a function from the JSZip library [23], which it requires as a dependency, to zip the files and encode the result to base64. 15 4. ANALYSIS A N D DESIGN 4.2.4 UnicVS UnicVS is the top-level part of this tool. It handles integration in Visual Studio Code and interaction with the user. Apart from adding UI elements to allow the user to run the analysis and to visualize its results it also handles collecting project data and processing the result. Visual Studio Extension Visual Studio Code continuously runs an event loop. Anything that happens when the IDE is open creates an event, to which functions can respond. Using the Extension API provided by Visual Studio Code [17] a developer can register functions to listen to the event loop. Visual Studio Code also includes a template extension with its extension API a developer can use to easily set up a new extension without building it from the ground up. UnicVS uses this template extension and registers a function to call analysis when the user requests it in the Visual Studio Code UI. It also defines other UI elements, such as notifications, progress updates, and visualisation of the analysis output. 4.3 Client-Domain Separation Much of the value of this project comes from separation of the client from the domain. By separating the functionality which handles the parsing and representation of the OSLC resources from the one which handles communication with Unite and the analysis, and making it independent of the specific OSLC domain, the program becomes much more versatile. The client part can be easily modified to suit the purposes of other OSLC domains and the OSLC representation can be used in any other JavaScript project working with any kind of OSLC resources. This would make it useful for example for Lotar [24], a project which aims to create standards for long-term data archivation and for which OSLC data is the most promising approach. Lotar needs a client compatible with all OSLC domains and separating the domains from the client is a great step towards that. 16 5 Implementation This chapter explores selected parts of the implementation, challenges in developing the client, and solutions to the problems which occurred during implementation. It also presents a guide on how to use this tool. 5.1 Oslcjs This section provides implementation details of the Oslcjs library and a guide on how to use it for OSLC domains other than just the automation domain. 5.1.1 Domain Definition Oslcjs aims to be reusable and extendable. For this reason, it defines a way to create new classes to represent other OSLC resources. This way, a user can easily use Oslcjs to create representation for any OSLC domain. This subsection presents the interface the user can use and its underlying mechanisms. OSLCResource As stated in Chapter 2, Oslcjs defines the OSLCResoruce class, which all other classes inherit from. OSLCResource holds all the data structures and methods needed to create new OSLC domains in Oslcjs. Registering a new resource To register a new resource, a user first has to create a new class and make it inherit from OSLCResource. Then they must write a static block for that class. The first line of the static block has to be an addOslcData() method call to initialize metadata. Next, oslcNamespace() must be called to register the namespace of this resource. Finally, oslcAttribute() must be called once for each attribute of the desired resource. In this method, the user defines the metadata for each attribute. Listing 5.1 shows an example of such resource definition. 17 5. IMPLEMENTATION Listing 5.1: Resource Definition Example c l a s s A u t o m a t i o n R e s u l t e x t e n d s O S L C R e s o u r c e { s t a t i c { t h i s . a d d O s l c D a t a () t h i s . o s l c N a m e s p a c e ( N S _ 0 S L C _ A U T 0 ) t h i s . o s l c A t t r i b u t e t h i s . o s l c A t t r i b u t e , N S _ 0 S L C _ A U T 0 + t h i s . o s l c A t t r i b u t e N S _ 0 S L C _ A U T 0 + " t h i s . o s l c A t t r i b u t e t h i s . o s l c A t t r i b u t e T _ L I T E R A L ) t h i s . o s l c A t t r i b u t e T _ L I T E R A L ) t h i s . o s l c A t t r i b u t e Z E R 0 _ 0 R _ 0 N E , T . t h i s . o s l c A t t r i b u t e ) t h i s . o s l c A t t r i b u t e T _ L I T E R A L ) t h i s . o s l c A t t r i b u t e " s t a t e " , N S _ 0 S L C _ A U T 0 , 0 N E _ 0 R _ M A N Y , T _ L I T E R A L ) " o u t p u t P a r a m e t e r " , N S _ 0 S L C _ A U T 0 , ZER0_0R_MANY P a r a m e t e r l n s t a n c e " ) " i n p u t P a r a m e t e r " , N S _ 0 S L C _ A U T 0 , Z E R 0 _ 0 R _ M A N Y , a r a m e t e r l n s t a n c e " ) " c r e a t e d " , N S _ D C T E R M S , Z E R 0 _ 0 R _ 0 N E , T _ L I T E R A L ) " i d e n t i f i e r " , N S _ D C T E R M S , E X A C T L Y , O N E , " d e s i r e d S t a t e " , N S _ 0 S L C _ A U T 0 , Z E R 0 _ 0 R _ 0 N E , " p r o d u c e d A u t o m a t i o n R e s u l t " , N S _ 0 S L C _ A U T 0 , I T E R A L ) " m o d i f i e d " , N S _ D C T E R M S , Z E R 0 _ 0 R _ 0 N E , T _ L I T E R A L " v e r d i c t " , N S _ 0 S L C _ A U T 0 , 0 N E _ 0 R _ M A N Y , ' r e p o r t s O n A u t o m a t i o n P l a n " , N S _ 0 S L C _ A U T 0 E X A C T L Y _ O N E , T _ L I T E R A L ) t h i s . o s l c A t t r i b u t e ( " c o n t r i b u t i o n " , N S _ 0 S L C _ A U T 0 , Z E R 0 _ 0 R _ M A N Y , N S _ 0 S L C _ A U T 0 + " C o n t r i b u t i o n " ) } Each of the methods used to define a class will now be discussed in more detail alongside their underlying mechanisms. Metadata Each OSLC resource has properties that store information about it. In Oslcjs, each of the properties is represented by an attribute of the OSLCResoruce object. Each of these properties has several characteristics defined by OSLC specification [14], such as name, allowed number of occurrences, or data type. This means each OSLCResource object needs to hold metadata with these characteristics. OSLCResource holds this metadata as an array of maps of objects. Each of the objects represents one property of the OSLCResource. Attributes of the object represent characteristics of that property. Each map then stores key-value pairs, where the value is the object, and the key is the full name of the property, including its namespace. When a new class representing a resource is created, the array of its parent class is inherited. Calling addOslcData then adds a new map as the first element of the inherited array. Configuring attributes for the resource 18 5. IMPLEMENTATION only changes this new map. Every time metadata is read, the array is searched sequentially from the first element, and the first encountered map containing the searched key returns the corresponding value. This means each new resource inherits all the metadata of its parent resource, but by configuring the attributes a user can override the inherited data without actually losing that information. Property configuration To add new property configuration, the user has to call a method called oslcAttribute once for each property they wish to configure. The oslcAttribute method currently has four arguments to configure the most fundamental traits of the property. Those are the property's name, its namespace, number of occurrences as defined by the OSLC specification [14], and the attribute's datatype. Each of these is essential to Oslcjs. The name and namespace uniquely define the property and are required both in serialize and deserialize functions to convert the property to text and back. The number of occurrences is used by Oslcjs to decide whether to represent the property as a single value or as an array. Finally, the type is used in the deserialize function as further explained in Section 5.1.2. Another option the user has when defining their class is registering post-serialize listeners to it. This is done by calling the registerPostSerializeListener static method of the OSLCResoruce class and giving it a callback function as an argument. The callback must take a string as an argument and return a string. In the last step of the serialize function, all registered callbacks are called on the resulting string to modify it before returning the result. This feature was added because sometimes it is necessary to correct or edit the request on the level of the serialized string. One listener is already registered to the OSLCResource class. It is called removeParseTypeResource, and it removes all instances of the substring 'parseType="resource'" from the string. This is a solution to a problem, which occurred because rdflib, which Oslcjs uses as a part of the serialize function, is not fully OSLC-compliant. Its behavior differs based on which format it serializes into. While there are no problems with serializing into Turtle, when serializing to XML, rdflib adds "parseType=resource" to each resource serialized from a BlankNode object. However, unite does not expect this tag and does 19 5. IMPLEMENTATION not process the request if the tag is present. Since whether or not rdflib adds the tag is based only on whether or not the serialized resource is an instance of BlankNode, there is no way to avoid this behavior in the code of Oslcjs. By adding the post-serialize listeners, Oslcjs is prepared for other potential problems of the same kind its user can encounter when reusing the code in their projects. 5.1.2 Deserialize Two different possible approaches were considered when developing the deserialize function, which parses data from X M L into the triple representation used by rdflib and then builds the object tree from it. This subsection describes each of them and their advantages and disadvantages. In both cases, the function first uses rdflib to transform the data from X M L text to a set of triples corresponding to the subject, predicate, and object as defined by RDF. The approaches differ in the way they transform these triples into an object graph. The first option is to go through the triples one by one and create all the JavaScript objects corresponding to the subjects of those triples. Then on a second pass-through, the function adds attributes corresponding to the predicates and fills their values with links to corresponding instances of the JavaScript objects based on the RDF object of the triple. A n advantage of this approach is that there is no need to store any extra metadata as all of the information needed is read directly from the X M L file. There are, however, several disadvantages to this approach, which make it less suitable than the second one. Firstly, there is no guarantee in what order the triples rdflib returned are iterated through. Because of that, there is no way to tell which one of these resources is the root of the object tree. This means extra functionality would have to be added to find the root of the tree, creating more overhead. Another problem this approach causes is creating a potential security vulnerability since which objects are created and edited is based on the data received through the internet. 20 5. IMPLEMENTATION The second approach is to create a new instance of an object representing the expected root resource. Then the function reads the metadata of that object, which store information about the expected attributes, and for each of the expected attributes, the function searches the triples to find one that corresponds to the relationship that attribute represents. If the type of the expected attribute is also an OSLC resource, the function creates a new instance of that resource and runs on it recursively. There are two disadvantages to this approach. The first one is that it requires Oslcjs to store metadata about the properties. Storing this data costs some memory, but more importantly, this information has to be defined when adding the class representing the OSLC resource, which means there is more work for the user. The more important disadvantage of the approach is that Oslcjs needs to know the type of the resource expected in the data being parsed beforehand. This, however, is not a problem for the purposes of this tool since the function is only called within http requests, where the type of the requested resource is known ahead. Furthermore, this approach has several advantages over the first one. Firstly, there is no problem finding the root as the root is passed to the function as a parameter. Secondly, the security vulnerability is reduced since triples containing unexpected data are never read. Additionally, this approach allows for validation of the data. Since in this approach the tool always knows what data it expects, functions can be set up to validate whether the expected matches the actual received data. 5.1.3 Validation Oslcjs currently supports simple validation of the parsed data. By calling the registerValidationListener method in the static block when defining a new resource, a user can register a validation function. When the resource is being deserialized, all registered validation functions are called. A validation function will be given an array of ValidationData objects, each with attributes containing information about one of the properties of the deserialized resource. This way a user can define validation functions that suit any OSLC domain. A simple validation function is provided by Oslcjs as a proof of concept. It compares the number of occurrences of each property in the X M L file 21 5. IMPLEMENTATION with the allowed number of occurrences defined by that property's metadata and shows a warning if those do not match. 5.2 UnicJS This section presents several problems encountered during the development of UnicJS and their solutions. 5.2.1 Zip As stated in Section 4.2.3, UnicJS uses zip to upload project data to the remote Unite server. Zip is a data archivation format assumed to be universal and therefore perfect for transferring data between two machines. However, when developing UnicJS, a problem occurred where Unite was not able to unzip the data zipped by UnicJS. This problem was discovered to be caused by Zip not being independent of the operating system. To save files and directories within a Zip archive, relative paths to the files are used. The format of a path is dependent on the operating system though. Unite expects paths within a Zip file in the Unix format, which separates directories within a path by a forward slash. However, Visual Studio Code is usually used on Windows and when zipping a file on a Windows machine, paths are supplied in the Windows format, where directories within a path are separated by a backslash. This problem was solved by normalizing paths to the Unix format before adding them to the Zip file. 5.2.2 Asynchrnous GET and POST When UnicJS communicates with Unite, it does several steps in sequence. Because of this, the first attempts in developing UnicJS used a synchronous version of GET and POST methods. A synchronous method waits for the completion of the network request and the return of a response before continuing. Using synchronous methods caused UnicJS to get stuck in a loop forever. 22 5. IMPLEMENTATION This behavior was caused by the way the XMLHttpRequest library achieves synchronization of HTTP requests. Because JavaScript is a single-threaded language, the library synchronizes an asynchronous operation using a synchronization file. The file is created when the operation starts and then the code waits in a while loop for a change in the file. When the operation is finished, the file is edited, the loop is broken and the calling code continues. This solution does not work when the function is run from a Visual Studio Code extension. This is because the synchronization file is created in a different place than the library expects it causing it to never edit the file. As a result, the while loop waits forever. Every solution to this problem has some disadvantages. One option is to modify the code of the library to fix the issue. However, that would mean the modified library would have to be maintained and updated with it. Another option would be to write a new library for sending HTTP requests. However, creating such a library would be difficult and it would be effort spent on creating something that essentially already exists, just to solve one bug. The option which was chosen is to use asynchronous HTTP methods and make the code of UnicJS asynchronous. This approach brought along with it additional advantages. It makes UnicJS functions not block the calling code. This can be useful in environments where functions are called directly in an event loop and while a function is running, the loop cannot continue to handle other events. Since an analysis by Unite can take anywhere from seconds to hours depending on the size of analyzed projects, this would freeze the loop, making such a program unusable. This would not be a problem for Visual Studio Code, which runs functions separately from its event loop, but could be one when the code of UnicJS is reused for a different project. 23 5. IMPLEMENTATION 5.2.3 Transient Errors When developing UnicJS a problem occurred where the program would non-deterministically crash with a 404 error in some cases. This happened because while polling the registered SUT prevents a situation in which analysis would be requested on a SUT that has not finished being registered, if the polling is done before the registration even starts, the resource for the registered SUT has not been created yet, which leads to a race condition and error 404 as the requested resource cannot be found. A similar problem occurred once the analysis was complete. While polling the server for the analysis state and result, an error 404 would occur sometimes. This happened because when Unite finishes the analysis, instead of modifying the Automation Result resource, which stores the analysis state and potentially the result, it deletes it and creates a new resource with the modified data. This means that if the request for the result happens during this brief window between deletion and creation, a race condition happens and error 404 occurs. Both of these problems are transient errors. UnicJS solves this issue by repeating the request when it fails with error 404. To prevent getting stuck on a non-transient error in this way, UnicJS tries to repeat the request three times with five seconds between each attempt. If the error persists, it is no longer considered transient, and UnicJS throws an appropriate error. 5.3 UnicVS This section provides some implementation details of UnicVS and describes a basic use case of UnicVS. 5.3.1 Input and Output All the functionality of UnicVS is provided using Visual Studio Code's Extension API. The analysis request is implemented as a one-button solution, requiring only minimal effort from the user. Graphical visualization of the result would be highly dependent on the tool used 24 5. IMPLEMENTATION by Unite. A solution would be possible, where UnicVS dynamically switches the form of the output based on the tool used, but it is beyond the scope of this thesis. For this reason, UnicVS visualizes the result as a simple text log. This makes it independent of the tool used by Unite. 5.3.2 Configuration UnicVS takes advantage of the support for user configuration of Visual Studio Code's extension API to allow the user to configure UnicVS for different analysis tools. By default, UnicVS is configured to interact with Facebook Infer. Despite this, configuration is needed the first time a user uses UnicVS to provide the U R L of the server Unite runs on. The configuration can be changed in Visual Studio Code's settings under File > Preferences > Settings > Extensions > UnicVS. The name of the tool, Unite URL, and compilation and analysis ports are accessible directly in the UI. The compilation and analysis arguments, which define the interaction with a tool have to be configured in the settings.json file, which is also accessible from the UI. The reason for this is that Visual Studio Code's setting UI does not support direct configuration of settings with a variable number of values and keyvalue pairs. Figure 5.1 shows the settings UI. Listing 5.2 shows the default settings.json 25 5- IMPLEMENTATION *Q File Edit Selection View G o Run = org. eclipse, wst mtidationprefs Settings-shared-Visual Stu... OD B CD OS — • X Settings X U settings.json • O "LD • • " Search settings E 7 ? User Wortespace > Secunty v Extensions .ipynb Support > C/C++ C# configuration C+ + TestMate Cltf5 CSS Language Features Emmet ES Lint Gh GitHub GitHub Enterprise Ser... Grunt GL p HTML isoi ,ske JavaScript Debugger . S O N Jupyter Markdown M a r k d o w n Matfi Merge Conflict Np™ P-P Pyiance Python Reference Search View Simple Browser Test Explorer Typescript UnkVS allOpenProjects UnicVS Analysis A r g u m e n t s Analysis Arguments Edit in settings.ison Analysis Port The analysis port of your Unite Compilation A r g u m e n t s Compilation Arguments Edit in settings.ison Compilation Port The compilation port of your Unite Turn o n Settings Sync Tool The tool for the analysis h f e ' Uil The uri your Unite is running o n http://localhost Figure 5.1: UnicVS Settings UI 26 5. IMPLEMENTATION Listing 5.2: Default settings.json { " c m a k e . c o n f i g u r e S e t t i n g s " : { " C M A K E _ T O O L C H A I N _ F I L E " : " C : / s r c / v c p k g / v c p k g / s c r i p t s / b u i l d s y s t e m s / v c p k g . c m a k e " }, " c m a k e . c o n f i g u r e O n O p e n " : t r u e , " t e s t M a t e . c p p . l o g . u s e r I d " : "3 b 9 a a c l 4 2 f 0 7 6 3 7 2 7 f 8 2 4 3 4 f 8 4 a 6 9 7 e 4 c 0 0 b 8 c 6 b " , " e d i t o r . u n i c o d e H i g h l i g h t . n o n B a s i c A S C I I " : f a l s e , " w o r k b e n c h . c o l o r T h e m e " : " D e f a u l t u H i g h u C o n t r a s t u L i g h t " , " u n i c E x t . c o m p A r g s " : { " b u i l d C o m m a n d " : " m v n u i n s t a l l " , " u n p a c k Z i p " : " t r u e " } } 5.3.3 Usage To use UnicVS, the user has to have a project open in Visual Studio Code. Then the user can request analysis by Unite in one of three ways. The first option is to right-click in the editor or in the explorer view on the left side of their screen and select "Run Unite Analysis" from the drop-down context menu. In these cases analysis is run on the project the user right-clicked on. The second option is to press the button in the top-right corner of the screen. In this case, analysis is run on the project that is currently open in the editor view. The final option is to open the command palette on the top of the screen or by using a keyboard shortcut with a default value of Ctrl+Shift+P and select "Run Unite Analysis" from the palette. With this option, if there is only one project open, analysis is run on that project. If multiple projects are open, a drop-down menu appears allowing the user to select the project they wish to analyze. After requesting analysis, a notification appears in the bottom-right corner of the screen, telling the user that analysis is in progress. This notification also has a progress bar and a short description of which step of communication the client is in at the current moment. Once the analysis is finished, a notification is shown to the user and the standard output of the Unite analysis appears in the log at the bottom of the screen. By using an adjacent drop-down menu, the user can switch between the standard output and the error output of the analysis. 27 5. IMPLEMENTATION >4 File Edit Selection View G o Run • settingsjson - shared - Visual ... C Q CD Do EXPLORER v SHARED > .settings - • X |5| m - > j o New File... New FolderReveal in File Explorer Open in Integrated Terminal Find in Folder... c m Copy clipse.wst.validation.prefs - Settings settings.json C: > Users > novae > AppData > Roaming > Code > User > O settings.json > {} unicvs.c 1 { " r n w ^ (-"-"i-i-FigureSettings" : { _TOOLCHAIN_FILE" : / s r c / v c p k g / v c p k g / s c r i p t s / b u i l d s y s t e m * Copy Path Copy Relative Path Shift+Alt+R : i g u r e O n O p e n " : t r u e , : p p . l o g . u s e r I d " : " 3 b 9 a a c l 4 2 f 0 7 6 3 7 2 7 f S ; . c o d e H i g h l i g h t . n o n B a s i c A S C I I " : f a l s e . Shift-i-Alt-i-F h " i E n o r e ^ r i m W h i t e s p a c e M : " F a l s e , c o l o r T h e n n e " : " D e f a u l t L i g h t s ™ , Ctrl+X l p i l a t i o n A r g u i n e n t s " : { ctri+c command": "mvn i n s t a l l " , : Z i p " : " t r u e " j .e" : " f a l s e " Shift + A l H C Ctrl+K Ctri+Shift+C Rename... Delete Run Unite Analysis F2 Delete Ln 16, Col 29 Spaces: 4 UTF-3 Lf C) JSON with Comments O Figure 5.2: UnicVS UI - Requesting Analysis Figure 5.2 shows the UI of Visual Studio Code with UnicVS installed and the first two ways to request analysis. On the left is the right-click context menu and on the right is the editor view button. Figure 5.3 shows the notification with progress tracking that is shown while analysis is in progress. Figure 5.4 shows the UI when the analysis is finished. Number one marks the notification about the completed analysis. Number two marks the output log where the analysis result is shown. Number three marks the button that can be used to switch between the standard output and the error output. 28 5. IMPLEMENTATION >4 File Edit Selection View Go Run ••• settings.json - shared - Visual S... C • • OS - • X EXPLORER ••• Settings + .gitignore 0 settmgsjson X » pot O Q HI " ' • SHARED O §1 C: > Users > novae > AppData > Roaming > Code > User > <] settings.json > EDunicvs.ui > .settings > sre J .classpath .project Si pom.xml > OUTLINE > TIMELINE 0 1 2 " c r r i a k e . c o n f i g u r - e S e t t i n g s " : { 3 " CMAK E_T0O LC HAI N_F I IL E " : 4 " C : / s r c / v c p k g / v c p k g / s c r i p t s / b u i l d s y s t e n s / v 5 }, 6 " c r r i a k e . c o n f i g u r e O n O p e n " : t r u e , 7 " t e s t M a t e . c p p . l o g . u s e r - I d " : " 3 b 9 a a c l 4 2 f 6 7 6 3 7 2 7 f B 2 4 3 " e d i t o r . u n i c o d e H i e h l i e h t . n o n B a s i c A S C I I " : f a l s e . PROBLEMS 2 6 7 . 2 6 8 . Unite Analysis Standard * a ~ x Found 5 i s s u e s ( c o n s o l e o u t p u t t r u n c a t e d t o Sj s e e ' / o s l c / c o m p i l a t i o n / S U T / 5 / i n f e r - o u t / r e p o r t . t x t ' f o r t h e f u l l l i s t ) I s s u e T y p e d S S U E D TYPE I D ) : # N u l l 0 Unite Analysis: Analysing Screen Reader Optimized Ln 19, Col 53 Spaces:4 UTT-8 LF CI JSON with Comments ft" £f Figure 5.3: UnicVS UI - Analysis in progress File Edit Selection View G o Run EXPLORER • SHARED > .settings > sre J .classpath ^ .gitignore = .project ft pom.xml > OUTLINE > TIMELINE settingsjson - shared - Visual S... C Q CD OS — • X ^ .gitignore U settingsjson X a por O ' Q CD •••Settings C: > Users > icvac > AopDsta > Roaming > Cede > User > [ \ settings.json > 0 unicvs.ui 1 " c m a k e . c o n f i g u r e S e t t i n g s " : { " CMAK_E_TOO LC HAI N_F IL E " : " C : / s r c / v c p k g / v c p k g / s c r i p t s / b u i l d s y s t e m s A }. " c m a k e . c o n f i g u r e u n u p e n " : t r u e , " t e s t M a t e . e p p . l o g . u s e r - I d " : " 3 b 9 a a c l 4 2 f B 7 6 3 7 2 7 f 8 2 4 3 " e d i t o r . u n i c o d e H i g h l i g h t . n o n B a s i c A S C I I " : f a l s e . OUT3 J"PROE-.EMS 2 6 7 . 2'5S. Found S i s s u e s ( c o n s o l e o u t p u t t r u n c a t e d t o 5^ s e e 1 / o s l c / c o m p i l a t i o n / S U T / S / i n f e r - o u t / r e p o r t . t x t ' f o r t h e f u l l l i s t ) I I s s u e T y p e ( I S S U E D _ T Y P E _ I D ) : * N u l l 0 Unite Analysis Complete Screen Reader Optimized Ln 19, Col 53 Spaces:4 UTT-8 LF t t JSON with Comments ft1 t ! Figure 5.4: UnicVS UI - Analysis finished 29 6 Evaluation This chapter summarizes the evaluation of the project and presents some ideas for improvements and future work. 6.1 Functional Requirements The first seven requirements from Section 4.1 are functional. The tool provides all the functionality required. Requirements 1 and 7 are satisfied by UnicVS which archives the project folder to be sent to Unite and shows the result in Visual Studio Code's output log. Requirements 2-6 are satisfied by the methods provided by UnicJS's Analyser. The tool has been evaluated using Facebook Infer running on remote servers provided by FIT. When correctly configured, the tool performed the process as expected. The reason Facebook Infer has been chosen for the evaluation is that Honeywell was contacted by engineers from Facebook asking for Visual Studio Code support for Facebook Infer. 6.2 Non-functional Requirements Requirements 8 and 9 are non-functional requirements. Requirement 8 is satisfied by Unite providing an OSLC-compliant service. Requirement 9 is satisfied as the communication the tool provides is fully compliant with OSLC Automation Specification 2.0 [14]. Currently, it supports Automation Request, Automation Result, and Automation Plan, which are necessary for code analysis by Unite and allows configuration for other OSLC domains. Because of this, the client can be used for any tool providing an OSLC-compliant service. UnicVS, which adds UI to Visual Studio Code adheres to the best practices outlined by Visual Studio Code Extension API guidelines [ 18 ] for adding user interface. This makes it compatible with other Visual Studio Code extensions and more intuitive for Visual Studio Code 30 6. EVALUATION users. The code of all three modules is also documented using JSDoc [25]. 6.3 User Testing The tool was user tested by developers from Honeywell. They were provided the tool, a simple guide on how to use the tool, and a questionnaire. They were asked to use the tool to analyze a project and answer the questions. The first half of the questions concerned how easy the tool is to use and configure. The users were asked to rank this on a scale from very easy to very difficult. A l l users found the tool very easy or easy to use and configure. The only part of the UI some of the users found difficult was reading the textual output log. The second half of the questions related to whether UnicVS works correctly and potential errors. In all cases, UnicVS worked as expected once the user configured it correctly. However, most of the users were shown at least one error because of the wrong configuration. The last question asked the users to provide their own commentary and suggestions for improvement. Some users wrote that they would prefer more descriptive error messages and a graphical representation of the results in the editor. 6.4 Future Work This section presents several ideas for improvements and future work on this tool. 6.4.1 Generating Class Code Currently, Oslcjs supports methods for users to manually add classes to map other domains besides automation. The implementation in Eclypse Lyo, however, uses external object models to automatically 31 6. EVALUATION generate appropriate code for their resource classes. A similar feature would be a valuable addition to Oslcjs as well in the future. 6.4.2 Downloading Resource Specification Currently, the metadata needed for the deserialize function and validations have to be provided by the user who defines the particular class. In the future, this could be changed to Oslcjs downloading the relevant metadata directly from Oslcjs specification. 6.4.3 Graphical Output Currently, UnicVS views the result of the analysis as a simple text log to retain independence of the tool used by Unite. In the future, it could instead implement functions to convert the output of the analysis into a graphical visualization for different tools and then choose the correct function based on the tool used. 32 7 Conclusion The goal of the thesis was to develop an OSLC-compliant client integrated into Visual Studio Code that is able to request analysis from Unite running on a remote server and visualize its results directly in the IDE. This goal has been achieved by the creation of three JavaScript modules - Oslcjs, UnicJS, and UnicVS. Oslcjs handles representation of OSLC data in JavaScript, which is needed to allow the sending of OSLCcompliant requests to Unite. UnicJS performs the communication with Unite, conducting the steps necessary for the actual analysis, and UnicVS provides the integration to Visual Studio Code, including the UI to request the analysis, configure the client, and show the results of the analysis to the user. The client has been evaluated using Facebook Infer and tested by engineers from Honeywell. The users found the tool easy to work with and it performed the analysis successfully when tested. The only issues the users had were notifications, progress updates, and configuration labels not being fully clear and understandable. While the client only uses the Automation Domain of OSLC, the code was made extendable and reusable for any OSLC domain. This was achieved by separating the code of the client from the particular domain, which means the same client can be easily modified to suit other OSLC domains, and providing an interface for the definition of OSLC domains as a part of the Oslcjs module. Each of the modules has also been made separately available to allow developers to reuse parts of the code relevant to their project. 33 Bibliography 1. Unite [online]. FIT [visited on 2022-11-26]. Available from: https: //pajda.fit.vutbr.cz/verifit/unite. 2. Project Arrowhead [online] [visited on 2022-12-06]. Available from: https://arrowhead.eu/. 3. Oslc Primer [online]. Steve Speicher [visited on 2022-11-29]. Available from: https : / / open - services . net / resources / oslc - primer/. 4. BUCAIONI, Alessio; S A A D A T M A N D , Mehrdad. OSLC Tool Integration and Systems Engineering - The Relationship Between The Two Worlds. In: 2014. Available from DOI: 10 . 1 1 0 9 / S E A A . 2014.64. 5. OSLC Specifications [online] [visited on 2022-12-07]. Available from: https://open-services.net/specif ications/. 6. Linked Data and OSLC Integration [online]. IBM [visited on 2022- 12-07]. Available from: https : //www. ibm. com/docs/en/elm/6. 0.5?topic=integrations-linked-data. 7. Oslc Specification [online]. OSLC [visited on 2022-11-26]. Available from:https://open-services.net/specifications/. 8. RDF Primer [online]. W3C [visited on 2022-12-07]. Available from: https: //www. w3. org/TR/rdf-primer/. 9. RDF Concepts [online]. W3C [visited on 2022-12-07]. Available from: https: //www. w3.org/TR/rdf 11-concepts/. 10. RDF Syntax [online]. W3C [visited on 2022-12-07]. Available from: https: //www. w3. org/TR/rdf-syntax-grammar/. 11. G A N D O N , Fabien; KRUMMENACHER, Reto; H A N , Sung-Kook; T O M A , loan. The Resource Description Framework and its Schema. 2011. 12. Extensible Markup Language (XML) 1.0 (Fifth Edition) [online]. W3C [visited on 2022-12-07]. Available from: https : //www. w3. org/TR/xml/. 13. RAY, Erik T. Learning XML: Creating Self-Describing Data. 1st ed. O'Reilly Media, 2001. ISBN 0-59600-046-4. 34 BIBLIOGRAPHY 14. OSLC Automation Specification Version 2.0 [online]. OSLC [visited on 2022-11-19]. Available from: https : //archive . openservices .net/wiki/automation/OSLC-Automation-Specification- Version-2.0/index.html. 15. Facebook Infer [online]. Facebook [visited on 2022-11-26]. Available from: https: //f binf er. com/. 16. Visual Studio Code [online] [visited on 2022-12-07]. Available from: https: //code. visualstudio. com/. 17. Extension API [online]. Visual Studio Code [visited on 2022-11- 16]. Available from: https://code.visualstudio.com/api. 18. UX Guidelines [online] [visited on 2022-12-06]. Available from: https://code.visualstudio.com/api/ux-guidelines/overview. 19. vscode-ext [online]. Pypi, 2021 [visited on 2022-07-13]. Available from: https: //pypi . org/project/vscode-ext. 20. oslc-client [online]. GitHub [visited on 2022-11-16]. Available from: https: //github. com/OSLC/oslc-client. 21. rdflib.js [online]. GitHub [visited on 2022-11-16]. Available from: https://github.com/linkeddata/rdflib.j s. 22. XMLHttpRequest [online]. npm [visited on 2022-11-17]. Available from: https: //www. npmj s . com/package/xmlhttprequest. 23. JSZip [online], npm [visited on 2022-11-18]. Available from: https://www.npmj s.com/package/j szip. 24. Lotar [online] [visited on 2022-12-06]. Available from: https : //lotar-international.org/. 25. Getting Started with JSDoc 3 [online] [visited on 2022-12-07]. Available from: https://jsdoc.app/about-getting-started.html. 35 A Source Code The source code of all three modules can be found in the attachments. Oslcjs and UnicJS can also be downloaded from the Npm. 36