+
Skip to content

Overview

Thomas Boby edited this page Jan 19, 2020 · 14 revisions

This article attempts to explain the various usage of this library by cwtools-vscode, the main consuming application. cwtools-vscode uses the cwtools library as a Language Server, and to implement https://microsoft.github.io/language-server-protocol/ . In order to do this a lot of the features of cwtools are based around providing the features required by that spec (validation, completion, hover, etc). However, the library can be used for more general analysis, in a similar way to most compiler services.

Game, the starting point

cwtools-vscode interacts with cwtools through the CWTools.Games.IGame interface. This interface provides methods like:

    abstract ValidationErrors : unit -> CWError list
    abstract LocalisationErrors : bool * bool -> CWError list
    abstract Complete : pos -> string -> string -> CompletionResponse list
    abstract GoToType : pos -> string -> string -> range option

To get hold of the interface, you use one of the game specific classes that implement it, such as CWTools.Games.Stellaris.STLGame and CWTools.Games.Custom.CustomGame. These factories all take the same setup settings CWTools.Games.GameSetupSettings and configure an internal instance of CWTools.Games.GameObject with the game specific customization. The GameObject does all the heavy lifting, then returns various services that are used to fulfill the IGame interface either directly or through helpers in CWTools.Games.LanguageFeatures.

A lot of the various xxxGame factories is probably a bit redundant, but they're all subtly different.

GameObject, setting everything up

From GameObject downwards everything should be agnostic of specific games. The primary purpose of this class is to create and recreate services as necessary, as well as perform the initial all file load. initialLoad() takes all files in the working directory, plus any embedded files (usually from vanilla), then passes them to the resource manager to be parsed. It makes sure that they're correctly filtered to prevent validation of vanilla files. This is the Loading project... stage of cwtools-vscode and about half of the loadtime.

The services it contains:

FileManager

FileManager is responsible for initial discovery and classification of files. Roughly, it:

  1. Takes a series of workspace roots and normalises them
  2. Classifies them into one of a. Vanilla, b. Multiple mod directory (containing .mod files), c. Direct mod folder (most common)
  3. Applies scriptFolders to find all files in the correct subfolders for this game
  4. Finds all files in those folders, classifies them by extension into one of a. EntityResourceInput (script file), b. FileResourceInput (name only), c. FileWithContentResourceInput (name + contents, e.g. csv and yml)
  5. Normalises the path for all files into one relative to mod/game root.

ResourceManager

ResourceManager is responsible for parsing script files as well as handling load order. Roughly, it:

  1. Takes a series of files as ResourceInputs
  2. Parses and "Process"es them if they're EntityResourceInputs
  3. Unpacks them if they're CachedResourceInput (embedded/cached files)
  4. Populates fileMap with all the loaded files
  5. Populates entityMap with all the parsed script files, and sets up the lazy ComputedData
  6. Marks all entities as Overwritten, Overwrote or No depending on load order, which is used to set validate to false for overwritten files, and filter overwritten files from functions such as allEntities.

After initial load UpdateFile is generally used on demand as the user edits files to update and reparse.

It exposes the IResourceAPI which is used for other services to get hold of entities/files.

LocalisationManager

Not too tricky, this manager uses IResourceAPI to get all localisation files and runs the given localisation parser to get all localisation for the required languages. It should correctly update its lists of localisation keys when individual loc files are updated, and also "processes" loc into forms more useful for validation and detailed analysis (as opposed to just getting the raw text).

ValidationManager

ValidationManager, unsurprisingly, manages all validation. It manages, caches, and updates the lists of errors as entities are changed.

Validation errors

Errors (or more accurately, Diagnostics) in cwtools are represented by the CWTools.Games.CWError class which is almost always held in a CWTools.Validation.ValidationResult wrapper:

type ValidationResult =
    | OK
    | Invalid of Guid *  CWError list

So, all validators return either OK or a list of errors (and a unique Guid used for equality).

Errors are usually created using CWTools.Validation.ValidationCore.inv which takes an ErrorCodes function and a location (a Node, Leaf, etc from the script data structure). They are easily merged using the operator <&&> which will simply concatenate the two lists. However, where possible, it's better to use the <&&&> operator to append a single error at a time, which improves performance. When applying a validation function to a collection, you can use <&!&>.

Validator

There are four main types of validation in cwtools:

  1. FileValidator, StructureValidator and LookupValidator are all self-contained validators that are given all changed entities as well as some context and can do whatever validation they want on them. This can result in a fair amount of redundant processing if they're too lazy. These are mainly used for fairly specific, complication, validators.
  2. LocalisationValidator as above, but returning specifically localisation errors
  3. Rules based validation. The bulk of validation is provided by the RuleValidationService, which derives rules from config files.
  4. Various custom validation. There are also a number of specific more custom validators scattered around, such as "global" localisation validators.

RulesManager

This is the brain of cwtools. So far everything is just simple parsing and tailored validation function. RulesManager takes a number of crowd-sourced configuration files such as https://github.com/cwtools/cwtools-hoi4-config/blob/master/Config/events.cwt and uses them as a schema to understand, analyse, and validate the script files.

This is all in CWTools.Rules namespace, with CWTools.Rules.RulesParser loading the rules and defining types, enums, etc. The rules format is very similar to pdxscript itself in order to simplify usage for modders. The rules format is explained here: https://github.com/tboby/cwtools/wiki/.cwt-config-file-guidance

RulesManager does a number of passes over the script files, finding all defined instances of types (such as event, focus, decision), enums (structurally defined) and "values" (contextually defined). It uses/creates RulesValidationService, InfoService and CompletionService to do this, and those are also the end-products which are used to power validation, completion and other IDE features as defined by the LSP.

Clone this wiki locally
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载