Inhaltsverzeichnis
Razvoj razširitev
Navodila za razvoj novih razširitev za WvdS FPC RAD Studio.
Predpogoji
- Nastavljeno razvojno okolje (glejte Začetek)
- Osnovno razumevanje Pascala in pas2js
- Poznavanje VSCode Extension API
Ustvarjanje nove razširitve
1. Ustvari strukturo imenikov
cd sources/extensions mkdir -p wvds.vscode.{name}/pas mkdir -p wvds.vscode.{name}/dist mkdir -p wvds.vscode.{name}/images
2. Ustvari package.json
{
"name": "wvds-vscode-{name}",
"displayName": "WvdS VSCode {Name}",
"description": "{Opis}",
"version": "0.1.0",
"publisher": "wvds",
"license": "MIT",
"icon": "images/icon.png",
"engines": {
"vscode": "^1.85.0"
},
"categories": ["Other"],
"main": "./dist/extension_main.js",
"activationEvents": [
"onCommand:wvds.{name}.{command}"
],
"contributes": {
"commands": [
{
"command": "wvds.{name}.{command}",
"title": "{Naslov}",
"category": "WvdS"
}
]
},
"extensionDependencies": [
"wvds.wvds-vscode-core"
]
}
3. Ustvari build.cfg
[build] compiler=pas2js target=vscode-extension entry=extension_main.pas [pas2js] options=-Jc -Jirtl.js -Tbrowser units=../../common;./pas output=./dist
4. Ustvari extension_main.pas
unit extension_main; {$mode objfpc}{$H+} interface uses JS, VSCode.API, VSCode.Commands, VSCode.ExtensionExports, WvdS.VSCode.Strings; procedure Activate(AContext: TExtensionContext); procedure Deactivate; implementation procedure Handle{Command}(Args: TJSValueDynArray); begin ShowInfoMessage(rs{Name}CommandExecuted); end; procedure DoActivate(AContext: TExtensionContext); begin // Registracija ukaza RegisterCommand('wvds.{name}.{command}', @Handle{Command}); // Beleženje LogInfo('WvdS {Name} razširitev aktivirana'); end; procedure Activate(AContext: TExtensionContext); begin try DoActivate(AContext); except on E: Exception do begin LogError(rsActivationFailed, [E.Message]); ShowErrorMessage(Format(rsActivationFailed, [E.Message])); end; end; end; procedure Deactivate; begin LogInfo('WvdS {Name} razširitev deaktivirana'); end; initialization ExportActivateDeactivate(@Activate, @Deactivate); end.
5. Prevedi
cd sources/extensions/wvds.vscode.{name} pas2js -Jc -Jirtl.js -Tbrowser \ -Fu../../common \ -Fu./pas \ -FE./dist \ pas/extension_main.pas
6. Testiraj
- F5 v VS Code → Extension Development Host
- Ukazna paleta →
WvdS: {Ukaz}
Upoštevanje plastne arhitekture
Modelna plast
// {Feature}.Models.pas unit {Feature}.Models; {$mode objfpc}{$H+} interface type // Zapisi za podatkovne strukture TWvdS{Feature}Config = record Name: string; Value: Integer; Enabled: Boolean; end; // Naštevanja TWvdS{Feature}Status = ( fsIdle, fsProcessing, fsCompleted, fsFailed ); // Polja TWvdS{Feature}ConfigArray = array of TWvdS{Feature}Config; implementation end.
Storitvena plast
// {Feature}.Service.pas unit {Feature}.Service; {$mode objfpc}{$H+} interface uses {Feature}.Models; // Validacija function ValidateConfig(const AConfig: TWvdS{Feature}Config): Boolean; // Operacije function ProcessData(const AInput: string): TWvdS{Feature}Config; // Poslovna logika procedure ExecuteFeature(const AConfig: TWvdS{Feature}Config); implementation uses SysUtils, WvdS.VSCode.Strings; function ValidateConfig(const AConfig: TWvdS{Feature}Config): Boolean; begin Result := (AConfig.Name <> '') and (AConfig.Value >= 0); end; function ProcessData(const AInput: string): TWvdS{Feature}Config; begin // Obdelava... Result.Name := AInput; Result.Value := Length(AInput); Result.Enabled := True; end; procedure ExecuteFeature(const AConfig: TWvdS{Feature}Config); begin if not ValidateConfig(AConfig) then raise Exception.Create(rs{Feature}InvalidConfig); // Izvajanje... end; end.
Plast razširitve
// extension_main.pas - samo UI logika procedure HandleCommand(Args: TJSValueDynArray); var Config: TWvdS{Feature}Config; begin // 1. Pridobi vnos iz UI Config := GetConfigFromDialog; // 2. Pokliči storitev (brez logike tukaj!) if not ValidateConfig(Config) then begin ShowWarningMessage(rs{Feature}InvalidInput); Exit; end; // 3. Izvedi try ExecuteFeature(Config); ShowInfoMessage(rs{Feature}Success); except on E: Exception do ShowErrorMessage(Format(rs{Feature}Failed, [E.Message])); end; end;
Uporaba VSCode API
Ukazi
// Registracija ukaza RegisterCommand('wvds.{name}.{action}', @Handler); // Izvajanje ukaza ExecuteCommand('wvds.other.action');
Konfiguracija
// Branje nastavitve var Value := GetConfiguration('wvds.{name}').Get('setting', DefaultValue); // Pisanje nastavitve GetConfiguration('wvds.{name}').Update('setting', NewValue, True);
Izhodni kanal
// Uporaba kanala (zagotovljen s strani Core) LogInfo('Informacija'); LogWarn('Opozorilo'); LogError('Napaka: %s', [E.Message]); LogDebug('Razhroščevanje: %s', [Data]); // Samo pri logLevel=debug
WebView
// Ustvari WebView panel var Panel := CreateWebviewPanel( 'wvds.{name}.view', 'Naslov', ViewColumn.One, WebviewOptions ); // Nastavi HTML Panel.Webview.Html := LoadTemplate('template.html'); // Sporočanje Panel.Webview.OnDidReceiveMessage(@HandleMessage); Panel.Webview.PostMessage(JSObject);
StatusBar
var StatusItem := CreateStatusBarItem(StatusBarAlignment.Left, 100); StatusItem.Text := '$(check) Pripravljeno'; StatusItem.Show;
Resourcestrings za i18n
Vsi nizi morajo biti definirani v WvdS.VSCode.Strings.pas!
// WvdS.VSCode.Strings.pas resourcestring // {Feature} Extension rs{Feature}CommandExecuted = '{Feature} command executed'; rs{Feature}InvalidConfig = 'Invalid configuration'; rs{Feature}Success = 'Operation completed successfully'; rs{Feature}Failed = 'Operation failed: %s';
// WvdS.VSCode.Strings.DE.pas resourcestring rs{Feature}CommandExecuted = '{Feature}-Befehl ausgeführt'; rs{Feature}InvalidConfig = 'Ungültige Konfiguration'; rs{Feature}Success = 'Vorgang erfolgreich abgeschlossen'; rs{Feature}Failed = 'Vorgang fehlgeschlagen: %s';
Obravnava napak
procedure SafeOperation; begin try DoRiskyOperation; except on E: EFileNotFoundException do begin LogError(rsFileNotFound, [E.FileName]); ShowErrorMessage(Format(rsFileNotFound, [E.FileName])); end; on E: EAccessDenied do begin LogError(rsAccessDenied, [E.Path]); ShowErrorMessage(Format(rsAccessDenied, [E.Path])); end; on E: Exception do begin LogError(rsUnexpectedError, [E.ClassName, E.Message]); ShowErrorMessage(Format(rsUnexpectedError, [E.ClassName, E.Message])); end; end; end;
Nikoli praznih except blokov! Vsako izjemo je treba obravnavati ali beležiti.
Razhroščevalno beleženje
{$IFDEF DEBUG} procedure LogDebugTrace(const AMessage: string); begin if not DebugEnabled then Exit; WriteDebugLog(Format('[%s] %s at %s', [ FormatDateTime('hh:nn:ss.zzz', Now), AMessage, GetCallStack ])); end; {$ENDIF}
Aktivacija:
- Prevedi z
-dDEBUG - Zaženi razširitev s parametrom
–debug
Pisanje testov
// Tests/{Feature}.Tests.pas unit {Feature}.Tests; {$mode objfpc}{$H+} interface uses TestFramework, {Feature}.Service, {Feature}.Models; type T{Feature}ServiceTest = class(TTestCase) published procedure TestValidateConfig_ValidInput_ReturnsTrue; procedure TestValidateConfig_EmptyName_ReturnsFalse; procedure TestProcessData_ValidInput_ReturnsConfig; end; implementation procedure T{Feature}ServiceTest.TestValidateConfig_ValidInput_ReturnsTrue; var Config: TWvdS{Feature}Config; begin Config.Name := 'Test'; Config.Value := 42; Config.Enabled := True; CheckTrue(ValidateConfig(Config)); end; procedure T{Feature}ServiceTest.TestValidateConfig_EmptyName_ReturnsFalse; var Config: TWvdS{Feature}Config; begin Config.Name := ''; Config.Value := 42; CheckFalse(ValidateConfig(Config)); end; end.
Kontrolni seznam pred potrditvijo
[ ] SoC upoštevano (Model/Service/Extension ločeni) [ ] Brez zakodiranih nizov (uporabljeni resourcestrings) [ ] Prevodi prisotni (EN, DE, SL, HR) [ ] Obravnava napak implementirana [ ] Razhroščevalno beleženje dodano [ ] Varnostne smernice preverjene [ ] Testi enot napisani [ ] README posodobljen [ ] CHANGELOG posodobljen
Glejte tudi
Zuletzt geändert: dne 29.01.2026 ob 22:23