Analysing Java with VSCode
VSCode is an incredible editor tool. Thanks to its extensions, one can develop using plenty of programming languages. However, what about analyzing one software system using VSCode?
In this blog post, I will present you how to use VSCode with Moose to analyze Java code. As an example, I will reproduce the blog post of Christopher Fuhrman.
Even if we can perform some analysis from VSCode, using the Moose tool natively gives a better user experience. Still, I believe it might interest people using only the VSCode tool.
- Install VSCode and the Pharo Language Server extension
- Set up the analysis of a new project
- Analysis
- Resources
Install VSCode and the Pharo Language Server extension
Download and install the required tools
To perform the analysis, we will use the insider version of VSCode. Currently, only this version supports the NoteBook feature we will use.
So, as a first step, install the last VSCode insider version.
We will also need a Moose image and a Pharo VM. For this blog post, we will use a Moose 8 image based on Pharo 8.
- Download the last Moose 8 image for VSCode and extract it.
- Download the corresponding Pharo VM and extract it.
Do not take the headless version (it has not been tested)
Once you have download VSCode, Moose 8, and the Pharo VM, we will install the extension in VSCode.
- Download the extension
- Open VSCode insider
- Open the folder in which the extension file is present
- Right-click on the file and execute
Install Extension
- Close VSCode
From now on, you must start VSCode insider with the following parameters (--enable-proposed-api badetitou.pharo-language-server
).
It allows VSCode to use the Notebook API.
Execute the following command in a terminal:
1code-insiders --enable-proposed-api badetitou.pharo-language-server
Or in Windows:
1code-insiders.cmd --enable-proposed-api badetitou.pharo-language-server
Configure VSCode
We now need to configure the Pharo Language Server extension. To do so:
- go in the VSCode settings (
Ctrl + ,
). - Search Pharo settings
- Set the field
Path To Image
with the path to the image you have downloadedD:\Users\benoit.verhaeghe\Documents\Pharo\images\LSP4\LSP4.image
- Set the field
Path To VM
with the path to the VM you have downloadedD:\Users\benoit.verhaeghe\Documents\Pharo\vms\80-x64\Pharo.exe
- Restart VSCode (to be sure the configuration is well saved)
If you use Windows, you might need to remove all space characters in the path.
Once the configuration is done, you can create a new file named oo-analysis.moosebook
.
It should open as a VSCode notebook and a Pharo image (you can reduce the Pharo image, but do not close it).
Set up the analysis of a new project
Clone the Java project you want to analyze
First, we are going to download the GitHub project we want to analyze.
To do so, create a new code cell
in VSCode with the following code:
1javaProjectFileRef := MooseEasyUtility cloneGitHubRepo: 'https://github.com/bethrobson/Head-First-Design-Patterns'.
This piece of code will download the project under our Pharo image folder. To execute the cell, press the run arrow next to the cell. In case of success, a little tick appears and the path to the clone project has output of the cell.
Parse the Java code to make FAMIX model
As in the original blog post of Christopher, now we will parse the Java project and create a FAMIX model. To parse the Java project, we use VerveineJ v1.x.x (v1.x.x works with Moose 8, whereas v2.x.x is under modification to work with the future Moose 9).
Contrary to the original blog post, we will download VerveineJ v1.0.2 (and not v1.0.1). It includes nice fixes.
-
Create a new code cell with the following piece of code to download the last VerveineJ version and extract it
1client := ZnClient new. 2 client 3 signalProgress: false; 4 url: 'https://github.com/moosetechnology/VerveineJ/archive/v1.0.2.zip'; 5 downloadTo: FileLocator imageDirectory. 6 client isSuccess 7 ifTrue: [ ZipArchive new 8 readFrom: (FileLocator imageDirectory / 'v1.0.2.zip') asFileReference pathString ; 9 extractAllTo: FileLocator imageDirectory. 10 11 "Since permissions are not preserved with ZipArchive#extractAllTo:" 12 "This line is not required in Windows system" 13 LibC runCommand: 'chmod u+x ', (FileLocator imageDirectory / 'VerveineJ-1.0.1/verveinej.sh') asFileReference pathString ] 14 ifFalse: [ Error signal: 'Download failed.' ]
-
Then, we will ask
MooseEasyFamixMaker
to parse the Java project using VerveineJ, and create a.mse
file for us. Again, in another cell, execute the following snippet of code.1wizard := MooseEasyFamixMaker 2 generateMSETo: 'tmp/HFDP.mse' asFileReference 3 parsing: 'tmp/MooseEasyRepos/bethrobson__Head-First-Design-Patterns' asFileReference 4 with: (FileLocator imageDirectory / 'VerveineJ-1.0.2/verveinej.bat') asFileReference. 5wizard generateMSE.
.mse
is a file format used by Moosetechnology to represent its model and meta-model. Other formats exist.
Load the model
The last step is to load the model in the Moose image (the one we are controlling using VSCode). In a new cell, execute:
1mseFileRef := 'tmp/HFDP.mse' asFileReference. "Generated by FamixMaker" 2mseStream := mseFileRef readStream. 3mseStream 4 ifNotNil: [ 5 mooseModel := MooseModel importFromMSEStream: mseStream. 6 mooseModel rootFolder: 7 'tmp/MooseEasyRepos/bethrobson__Head-First-Design-Patterns'. 8 mseStream close. ] 9 ifNil: [ self error: 10 'Could not load MSE file into Moose: ' , mseFileRef asString ]. 11mseStream. 12mooseModel install
The output of the cell should be a MooseModel #HFDP(30946)
.
Congrats! You have set up everything. Now it is time to analyze the project 🚀
Analysis
Visualize a Java package in PlantUML
To visualize Java packages using PlantUML.
We first install the PlantUML connector of Pharo (PlantUMLPharoGizmo
).
To do so, simply create a new code cell with the installation script and execute it.
1"Install PlantUMLPharo" 2version := 'master'. 3Metacello new 4 repository: 'github://fuhrmanator/PlantUMLPharoGizmo:' , version, '/src'; 5 baseline: 'PUGizmo'; 6 load.
Then, you can visualize the classes of a package by executing a Pharo Script.
1attribute := true. 2method := false. 3inheritance := true. 4aggregation := true. 5createCheckBox := false. 6 7preference := 'set namespaceSeparator ::' , String cr 8 , 'hide empty members' , String cr , 'scale 1' , String cr 9 , 'left to right direction' , String cr. 10 11items := mooseModel allModelClasses select: [:each | each mooseName beginsWith: 'headfirst::designpatterns::combining::decorator' ]. 12 13 14pUMLSource := PUGizmo 15 plantUMLSourceForMooseJavaClasses: items 16 withPreference: preference 17 withRelationships: 18 {attribute. 19 method. 20 inheritance. 21 aggregation. 22 createCheckBox}. 23 24plantKey := pUMLSource asPlantUMLKey. 25serverUrl := 'https://www.plantuml.com/plantuml/', plantKey. 26imageMorph := (ZnEasy getPng: serverUrl asUrl).
In the above example, as in the original blog post, we focus on the package: headfirst::designpatterns::combining::decorator
and we show the classes attributes, inheritances, and aggregation.
Executing the code gives the following image as the output of the VSCode cell.
Perform a Moose analysis using Pharo
It is also possible to execute some classic Pharo code. We can request the list of classes that implement more than one interface.
1"Query all classes that have more than two direct FAMIX superclasses" 2classesImplementingMoreThanOneInterface := mooseModel allModelClasses 3 select: [ :each | 4 each directSuperclasses size > 2 ]. 5String streamContents: [ :stream | classesImplementingMoreThanOneInterface do: [:class | stream << class name ] separatedBy: [stream << ', ' ] ]
Visualisation with Roassal
Finally, one can use Roassal2 (or Roassal3 in Pharo 9) to create custom visualization.
It is possible to use pre-built visualization coming from Moose, such as the System Nesting map:
1view := RTView new. 2FAMIXSystemNestingMap new 3 viewNamespaces: (mooseModel allNamespaces select: [ :each | each allClasses anySatisfy: [ :c | c isStub not ] ]) 4 highlighting: {} 5 onRaw: view. 6view
Or every other Roassal visualization!