-
Notifications
You must be signed in to change notification settings - Fork 4
Code documentation
-
Plugin specific files
-
the plugin needs to store different kinds of files: configuration files, survey results, recorded events, program snapshots, etc
-
because of the nature of how IJ and Eclipse run, there are multiple paths where the plugin stores its files. When you open a project in IJ or a workspace in Eclipse, both IJ and Eclipse spawn a new instance of the IDE over that project / workspace. This means that both IDEs have two kinds of locations: the installation location of the IDE (where the IDE stores information relevant to all IDE instances, like common settings for all plugins) and the instance location (where the IDE stores information relevant only to a specific instance). This means that in both Eclipse and IJ plugins have two storage spaces. Thus, our plugin also has two storage paths: the local storage (specific to each project / workspace) and the bundle storage (common to all IDE instances). There is one bundle storage, and multiple local storages.
- the local storage: eventFiles, workspace properties ("config"), logs, project snapshots, projects to ignore, known projects
- the bundle storage: install properties ("config-install") that are global to all instances (e.g., uninstall date, FTP settings), survey responses, participant
-
since our plugin supports updates, and since the event format may change from update to update, we store version sensitive files in versioned files
-
StorageManager knows how to provide the local and bundle storage, and versioned variants
-
File syncing between the local storage and the bundle storage
-
the user may perform activities that lead to the deletion of the plugin's files (upgrading the IDE leads to the deletion of the bundle storage, deleting or creating new projects or workspaces leads to new local storage). When this happens we do not want to redo certain tasks, like running the survey or resetting the uninstall date. To prevent this, we backup the bundle storage in all the local storages.
-
we also use the backup mechanism to detect new installations (when the bundle storage files do not exist anywhere) and perform installation specific tasks (e.g., running the survey).
-
the policy for backup is implemented in Installer and InstallerOperation
-
Uninstall
-
plugin must stop recording after a certain amount of time
-
Uninstaller is responsible for knowing when the plugin should shut down. The uninstall date is set at plugin installation
-
Snapshots
-
we need to snapshot the entire project on certain key moments:
- Eclipse:
- recording an event in a previously unrecorded project
- when the IDE is closed
- when plugin is updated
- IJ:
- when the plugin is first started
- when the IDE is closed
- when the plugin is update
- Eclipse:
-
snapshotting is useful for:
- it allows us to build the entire recorded project after any change
- if there is a recording error that would cause spurious replay, snapshotting at regular intervals reduces the section length of bad recordings
-
Event recording
-
overall picture: Multiple IDE specific listeners are subscribed at plugin startup. Each event listener records the event via the IDE agnostic ClientRecorder.
-
recorded events
- The Events enum contains all the events the plugin is currently recording
-
decoupling event format, storage format, and server storage
- the event format (currently JSON) is specified by the ClientRecorder
- the storage format is specified by ChangePersister and subclasses of the FileProvider. Currently each calendar day has an event file with all the events recorded in that day.
-
Plugin update
- each IDE implements its own update mechanism. Our plugin detects when it has been magically updated by the IDE and creates new versioned storage files to reflect the new update version (Installer.doUpdate()).
-
Choose which projects to record
-
Entry methods (main methods)
-
These are methods where the control flow of the plugin starts. It's good to read them to get a sense of how all the supported use cases are instantiated. Reading both Eclipse and IJ entry methods gives you a good sense of the common concepts
-
IntelliJ: recording is performed on a per project basis (an opened instance of IJ has only one project)
- entry point: COPEComponent.projectOpened()
-
Eclipse: recording is performed on a per workspace basis (an opened instance of Eclipse has multiple projects)
- entry point: COPEPlugin.start() which then calls StartPluginUIJob.runInUIThread()
-
IDE agnostic interfaces
-
These interface (and abstract classes) reside in the common infrastructure repository and define common functionalities for both IDEs. Both IDEs implement these interfaces.
-
StorageManager: provides the IDE specific paths to the local storage, the bundle storage, and to the versioned variants of these paths (see section on plugin stored files).
-
Installer
- InstallerHelper
- InstallerOperation
- SurveyOperation
-
RecorderFacade