boboyr / Compétences pour plugins Tiecode

Guide complet pour le développement de plugins pour Tiecode (IDE Tiecode / QiStudio). Couvre l'API plugin (com.rapid.api.* / studio-api.jar), les points d'extension program.json, le packaging .rmx, et l'implémentation de diverses fonctionnalités : complétion de code (TextMate + LanguageEngine + LSP), arborescence de fichiers (PSObject/ExpansionCase/CreationOption/OpeningOption), configurations d'exécution (RunConfiguration/TaskRunConfiguration), sélecteur de nouveau fichier, modèles de projet (BaseTemplate), tâches de compilation (BaseTask/ToolchainService), chaînes d'outils, coloration syntaxique, menus, pages de paramètres, etc. À utiliser lors du développement, de la modification, de l'apprentissage ou du débogage de plugins Tiecode, de plugins IDE Tiecode, de plugins .rmx, de plugins Tiecode, ou de plugins pour les langages go/scala/kotlin/linux/aar.

Qu'est-ce que Compétences pour plugins Tiecode ?

Cette compétence fournit un guide exhaustif et technique pour le développement de plugins dans l'environnement de développement intégré (IDE) Tiecode, également connu sous le nom de QiStudio. Elle est destinée aux développeurs souhaitant créer des extensions (packagées au format `.rmx`) pour personnaliser et enrichir l'IDE. La compétence détaille l'architecture modulaire du système, les points d'extension clés (déclarés dans `program.json`), et explique comment implémenter des fonctionnalités avancées comme la complétion de code via LSP, la gestion de l'arborescence de fichiers, les configurations d'exécution personnalisées, ou encore l'intégration de chaînes d'outils de compilation. Basée sur l'ingénierie inverse de l'API officielle et de nombreux plugins réels, elle couvre les aspects essentiels du SDK `com.rapid.api.*` et offre des exemples concrets pour Go, Scala, Kotlin, les applications Android (aar), et Linux. Les utilisateurs y trouveront des références aux dépôts officiels et communautaires, ainsi que des extraits de code Java prêts à l'emploi pour démarrer le développement de plugins.

Compatible avec~Claude Code~Codex CLI✓Cursor
npx skills add boboyr/TiecodePluginSkills

Installed? Explore more Productivité et collaboration skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Développement de plugins Tiecode

Documentation destinée au développement de plugins pour l'IDE « Tiecode / QiStudio » (nom du package hôte : com.tiecode.develop). Le nom officiel de « Tiecode Studio » est QiStudio (nouvelle plateforme open engineering, première application mobile à implémenter le standard OSGi, qui étend l'environnement de développement d'ingénierie sous forme de « micro-composants / plugins »). Sources : Rétro-ingénierie de studio-api-1.0-preview5.jar (com.rapid.api.*) + reconstitution du code source d'une douzaine de plugins réels (go / scala / kotlin / linux / aar / libgdx / exécution sans installation, etc.)


Documentation officielle et dépôts (important)

Dépôts officiels sur Gitee

DépôtDescription
MobileIPE-Plugin-DevManualTutoriel officiel de développement de plugins (micro-composants QiStudio). Contient QiStudio核心体系介绍.md, Rapid框架介绍.md, plugin/扩展点介绍.md, plugin/插件清单配置.md, plugin/注册你的微组件——插件.md
TiecodeCompiler-PublicDépôt de livraison du compilateur Tiecode (version multiplateforme). Contient docs/ (documentation sur l'utilisation du compilateur, la syntaxe, l'encapsulation, l'intégration de plateforme), headers/tiec/ (API C + en-têtes d'encapsulation C++), prebuilt/ (bibliothèques dynamiques cli + android/windows/linux/ohos/wasm), stdlibs/ (bibliothèques de base Android/CXX/Web)
QiStudio-PluginSamplesEnsemble d'exemples de plugins officiels (19+ exemples : injection de dépendances, animations éditeur/parenthèses arc-en-ciel, journal flottant, gestionnaire de projet Html, requêtes réseau, extension d'icônes, chaîne d'outils Javac9, coloration syntaxique, thème personnalisé, cycle de vie Application, composants de projet, divers menus, pages d'outils, pages de paramètres, etc.)

Le nom officiel du jar de l'API est qistudio-api-<version>.jar (le studio-api-1.0-preview5.jar rétro-conçu dans cette compétence est le SDK côté hôte). Groupe de discussion QQ : 1016399857.

Références d'implémentation communautaire (GitHub)

Ensemble de codes sources de plugins réels associé à cette compétence (dépôt unique avec plusieurs répertoires, contenant 8 plugins complets et compilables) :

https://github.com/boboyr/tiecode-plugin

RépertoirePluginCapacités démontrées
go语言工程插件/Projet langage Go (console + SDL3)Double modèle + complétion LSP(gopls) + coloration TextMate + chaîne d'outils + configuration d'exécution + nœud virtuel d'arborescence de fichiers
结绳安卓工程aar构建插件/Construction aar/jarRéutilisation de la chaîne de compilation hôte + sortie chinoise NameGenerator
结绳免安装运行插件/Exécuteur sans installationRéutilisation des tâches hôtes + chargement par plugin d'APK non installé
libgdx游戏编辑器插件/Éditeur visuel libgdxConcepteur + menu de la zone de code de l'éditeur + création de classe de scène
scala安卓工程插件/Projet Android ScalaChaîne de construction sbt complète + modèle « Projet plugin Tiecode » + plugin de construction/débogage
结绳Linux工程插件/Projet Tiecode Linux-SDL3Chaîne d'outils GCC + SDL3 + chaîne de tâches
外部kotlin文件注解插件/Annotation de fichier Kotlin externeAPI du compilateur Tiecode : CompilerPlugin + AnnotationProcessor + complétion Kotlin
BasicLanguages-lang参考/Langage de base officielRéférence de coloration syntaxique csml/json/markdown/xml/properties

0. Concepts fondamentaux et architecture globale

Tiecode est un IDE hôte modulaire. Les plugins sont distribués sous forme de fichiers .rmx. Un .rmx est essentiellement une APK : AndroidManifest.xml + classes.dex + META-INF/program.json. L'hôte découvre les capacités du plugin via les points d'extension déclarés dans program.json, et non via <application> ou les quatre composants principaux du manifeste.

0.1 Trois packages clés

PackageRôle
com.rapid.api.*SDK du plugin (principal sujet de ce document). Ingénierie, langage, tâche, structure, page, UI, réseau, etc.
com.rapid.framework.*Couche framework : VFS (système de fichiers virtuel), clés Service/Data/Event, conteneur program/plugin
com.tiecode.compiler.*Compilateur Tiecode (arbre syntaxique / table des symboles / completer/processor de chaîne d'outils) — côté hôte, le plugin utilise généralement uniquement son sous-paquet toolchain

0.2 Points d'extension (tableau extension de program.json)

Structure complète de META-INF/program.json :

{
  "id": "com.goproject.plugin",
  "name": "go语言工程插件",
  "engine": "plugin",
  "description": "...",
  "versionCode": 4,
  "versionName": "1.3",
  "minSupport": 1,
  "vendor": { "name": "boboyr", "email": "", "url": "#" },
  "extension": [
    { "point": "application", "class": "com.goproject.plugin.MyApplication" },
    { "point": "project.manager", "class": "com.goproject.plugin.project.GoProjectManager" },
    { "point": "project.language", "class": "com.goproject.plugin.lang.GoLanguageFactory",
      "scope": { "unit": "project", "identifiers": "sample.go" } },
    { "point": "domain.menu", "class": "com.goproject.plugin.Gomodmenu" }
  ]
}

Explication du champ minSupport (version minimale de l'hôte requise)

minSupport est un entier indiquant la version minimale de Tiecode requise par le plugin. Les valeurs diffèrent selon la version :

Version de TiecodeminSupportDescription
Tiecode 4.61Pour un plugin 4.6, écrire "minSupport": 1
Tiecode 4.72Pour un plugin 4.7, écrire "minSupport": 2

C'est-à-dire : lors du développement d'un plugin pour 4.6, minSupport doit être 1 ; pour une mise à niveau vers 4.7 (ou un plugin destiné à 4.7), mettre 2. Les règles exactes de liaison avec la version de l'hôte sont à confirmer officiellement ; lors du développement, veuillez remplir selon la version cible de l'hôte.

Ensemble complet des points d'extension confirmés (champ point) :

Point d'extensionClasse à implémenter/hériterRôleSource du plugin
applicationAndroidPluginPoint d'entrée du plugin, onInit/activate/onUninstallgo/scala/aar/sans installation
project.managerProjectManager (couramment CodeProjectManager)Enregistrer un type de projetgo/scala/linux
project.languageLanguageFactoryEnregistrer un langage (coloration + extension de fichier associée), peut avoir un scopego/scala
project.language.engineLanguageEngineEnregistrer un moteur de langage (conteneur de providers comme la complétion, le diagnostic)Plugin console Tiecode
project.toolchainSous-classe de Tool (ex. SunJdk8Compiler)Enregistrer une chaîne d'outils de compilationJavaCompiler8
project.componentComponentIntegrator/ComponentFactoryMonter des composants à l'ouverture du projet (configuration d'exécution/première fenêtre contextuelle/hook)linux/kotlin/aar/sans installation
project.file.creationOptionPSObjectCreationOptionÉlément de menu « Nouveau fichier » dans l'arborescencekotlin/libgdx
project.file.openWithEditorPSObjectOpeningOption« Ouvrir avec » pour les fichierskotlin
project.event.fileUiProjectFileUiEventÉvénement UI de l'arborescence (lier des icônes, etc.)kotlin
domain.menuBaseDomainMenuAction/action de menuÉlément de menu de premier niveaugo
domain.menu.editor.codeMenu de la zone de code de l'éditeurlibgdx
platform.settingsBuilderSettingsBuilderAjouter une sous-page de paramètresscala Android
project.file.creationOption———

Remarque : scope.identifiers sert à limiter un langage/composant à un typeId de projet spécifique (ex. sample.go). La classe de certains points d'extension peut être None (espace réservé).


1. Point d'entrée du plugin : point d'extension application

import com.rapid.framework.program.android.app.AndroidPlugin;
import com.rapid.framework.program.android.DvmPluginDescriptor;
import com.rapid.api.Platform;
import com.rapid.api.framework.project.toolchain.ToolchainService;
import com.rapid.api.framework.project.ProjectServiceKeys;

public class MyApplication extends AndroidPlugin {
    @Override
    public void onInit(DvmPluginDescriptor descriptor) {
        // Enregistrer une chaîne d'outils de compilation personnalisée (exemple : compilateur Go)
        ToolchainService service = Platform.getService(ProjectServiceKeys.TOOLCHAIN);
        service.setTool(GoCompileApiKeys.Gocompile, new BaseGoCompiler());
    }
    @Override
    public void activate() {
        // Exécuté une fois lors de l'activation du plugin (contient souvent des hooks, des écouteurs, l'assemblage du plugin de compilation)
    }
    @Override
    public void onUninstall() {
        // Nettoyage à la désinstallation : terminer ses propres processus enfants (ex. gopls), déconnecter LSP
    }
}

API clé (com.rapid.api.Platform) :

  • Platform.getService(Key<T>) — Récupérer un service hôte (ex. ProjectServiceKeys.TOOLCHAIN)
  • Platform.getProject() — Objet du projet actuellement ouvert
  • Platform.getApplicationContext() — Contexte hôte

2. Type de projet : point d'extension project.manager

Un plugin enregistre un « type de projet » (ex. projet langage Go, projet Android Tiecode) via ProjectManager.

2.1 Squelette du gestionnaire

public class GoProjectManager extends CodeProjectManager<GoProject> {
    public final static String TYPE = "go语言工程";       // Nom affiché
    public final static String IDENTIFIER = "sample.go"; // typeId, stocké dans project.json

    public GoProjectManager() {
        super();
        this.fileManager = new GoFileManager();   // Optionnel : gestionnaire de fichiers personnalisé (lier des icônes, etc.)

        // ① Ouverture de fichier (par extension)
        fileManager.addPSObjectOpeningOption(DefaultOpeningOption.INSTANCE, ".go", ".mod");
        // ② Expansion des nœuds de l'arborescence (nœud virtuel « Bibliothèques externes »)
        fileManager.addPSObjectExpansionCase(new ExternalLibrariesExpansionCase(), MARKER);
        // ③ Élément de menu Nouveau fichier
        fileManager.addPSObjectCreationOption(new GoFileCreationOption());
        // ④ Moteur de langage et fabrique de langage
        languageManager.registerEngine("go", GoLanguageEngine.getInstance());
        languageManager.registerLanguageFactory(new GoLanguageFactory());
        languageManager.registerOperatorProvider(GoLanguage.ID, new GoOperatorProvider());
        // ⑤ Modèles de création de projet
        addTemplate(new GoConsoleTemplate());
        addTemplate(new GoSdl3Template());
    }

    @Override public String getIdentifier() { return IDENTIFIER; }

    @Override public TypeDescription getTypeDescription() {
        Drawable d = ContextUtils.getDrawable(AndroidPlugins.getContext(this), R.drawable.golang);
        return new TypeDescription(TYPE, TypeDescription.APPLICATION, d);
    }

    @Override public GoProject newProject() { return new GoProject(); }

    @Override public boolean isProjectDir(File file) { return false; }
}

Méthodes de l'interface ProjectManager (d'après javap) :

String getIdentifier();
TypeDescription getTypeDescription();      // Nom + type + icône
List<Template<T>> getTemplates();
void addTemplate(Template<T>);
ProjectFileManager<T> getFileManager();
T newProject();
void load(T, LoadingPresentation);
boolean isProjectDir(File);                // Déterminer si un répertoire est de ce type de projet
String backup(T); void delete(T);

Constantes de type pour TypeDescription : APPLICATION / CONSOLE / LIBRARY.


3. Objet projet et assemblage du pipeline : CodeProject.prepare()

Un type de projet correspond à une sous-classe de Project. prepare() est appelé par l'hôte à l'ouverture du projet, à ce moment les fichiers modèles ont déjà été écrits, et on peut assembler la chaîne de tâches, les configurations d'exécution et les composants en fonction du contenu du répertoire.

public class GoProject extends CodeProject {
    @Override
    public void prepare() {
        if (GoProjectKind.isSdl3(getProjectDir())) {
            Task buildLibmain = new BuildLibmainTask();
            Task publishLib = new PublishLibTask();
            addTask(buildLibmain);
            addTask(publishLib);
            publishLib.dependsOn(buildLibmain);      // Dépendance de tâche
            addRunConfiguration(new GoSdl3RunConfiguration());
        } else {
            addTask(new CompilerGoTask());
            addTask(new RunGoTask());
            addRunConfiguration(new GoStartRunConfig());
            addRunConfiguration(new ElfRunConfig());
        }
    }
    @Override public ProjectVariant getVariant() { return ProjectVariant.DEBUG; }
}

Méthodes clés de CodeProject (qui étend BaseProject) :

void prepare();
TaskContainer getTasks();  TaskExecutor getTaskExecutor();
void addTask(Task);  void setTasks(Iterable<Task>);
void addRunConfiguration(RunConfiguration);   // Propre à CodeProject
ProjectVariant getVariant();  void setVariant(ProjectVariant);
Logger getLogger();  void setLogger(Logger);
String getName();
File getProjectDir();  File getChildFile(String);   // Résoudre un chemin relatif en File
void recycle();

Valeurs de ProjectVariant : DEBUG / RELEASE / UNDEFINED.

Astuce (du plugin Go) : dans prepare(), écrire des fichiers marqueurs (ex. External Libraries) pour ajouter des capacités à un projet existant en une seule fois, sans avoir à le recréer.


4. Modèle de projet : BaseTemplate

Un modèle détermine les options disponibles dans la boîte de dialogue « Nouveau projet » et les fichiers écrits lors de la création.

public class GoConsoleTemplate extends BaseTemplate<GoProject> {
    @Override public String getName() { return "控制台工程"; }
    @Override public Drawable getPicture() { return null; }        // Aperçu du modèle, peut être null
    @Override public String getDefaultProjectName() { return "我的go控制台工程"; }
    @Override public Form getForm() { return new Form(); }         // Peut ajouter des champs de saisie

    @Override public void create(GoProject project, Form form,
                                 Project.OnProjectCreateListener listener) {
        try {
            File file = project.getChildFile("src/main.go");
            String html = AssetUtils.readAsset(AndroidPlugins.getContext(this), "sample/main.go");
            html = html.replace("${project_name}", project.getName());
            FileUtils.writeFile(html, file);                        // Écrire dans le répertoire du projet
            FileUtils.writeFile("module main\ngo 1.26.0", project.getChildFile("src/go.mod"));
            listener.onSuccess();                                    // Callback de succès
        } catch (IOException e) {
            listener.onFail("写出默认文件失败");                      // Callback d'échec
        }
    }
}

Méthodes de l'interface Template<T> :

String getName();
Drawable getPicture();
String getDefaultProjectName();
Form getForm();          // com.rapid.framework.data.form.Form, peut utiliser addInput(new FormInput(...))
void create(T, Form, OnProjectCreateListener);   // OnProjectCreateListener.onSuccess()/onFail(msg)

Ressources transportées par le modèle : inclure les fichiers du modèle dans app/src/main/assets/<nom>, utiliser AssetUtils.readAsset / AssetUtils.unZipAssetsFolder(context, zipName, destDir) pour les lire et les décompresser. (Le modèle de projet SDL3 décompresse entièrement gosdl3_template.zip depuis asset vers le répertoire du projet.)


5. Tâche de compilation et chaîne d'outils : BaseTask + ToolchainService

5.1 Tâche BaseTask

public class CompilerGoTask extends BaseTask {
    @Override public void execute() throws TaskInterruptError {
        File output = new File(Platform.getProject().getProjectDir() + "/output");
        if (!output.exists()) output.mkdirs();
        GoCompile a = Platform.getService(ProjectServiceKeys.TOOLCHAIN)
                             .getTool(GoCompileApiKeys.Gocompile);
        if (!a.isInstalled(ctx)) { logger.info("安装工具链..."); a.install(ctx); }
        GoCompileParams p = new GoCompileParams();
        p.inputFiles = FileUtils.getGofile(srcDir);
        p.outputPath = output.getPath();
        p.options = new String[]{"build", "-o"};
        a.compile(p, new CompileOnExecutionCallback());
    }

    // Doit être redéfini : BaseTask.prepare par défaut lance UnsupportedOperationException ;
    // De plus, les champs logger/variant doivent être assignés ici, sinon logger.info dans execute() provoquera un NPE.
    @Override public void prepare(Project project, ProjectVariant variant, Logger logger) {
        this.logger = logger;
        this.variant = variant;
        Os.setenv("GOROOT", goRoot, false);   // Définir la variable d'environnement (android.system.Os)
    }

    @Override public String getId() { return "compileWithGo"; }   // Pour référence par getTaskId() de la configuration d'exécution
    @Override public String getName() { return "编译到目标平台"; }
}

Interface Task (d'après javap) :

String getId();  String getName();
void prepare(Project, ProjectVariant, Logger);      // Remarque : par défaut, lève une exception, assurez-vous de la redéfinir
void execute() throws TaskInterruptError;
TaskState getState();
void interrupt();
void dependsOn(Task...);  void dependsOn(List<Task>);
Task getDependencyTask(String);  Task getDependencyTaskByName(String);
String getIntermediatePath();  String getIntermediatePath(String);
String getOutputPath();  String getOutputPath(String);
File getGeneratedDir();

Piège (note du plugin Go) : si logger n'est pas assigné dans la tâche, utiliser logger.info dans execute() provoque un NPE et l'installation de la chaîne d'outils ne s'exécute jamais.

5.2 Chaîne d'outils Tool + Installable

public interface Tool { /* Contient les clés intégrées ANDROID_SDK/AAPT/AAPT2/D8/R8/DX/PROGUARD/
                         MANIFEST_MERGER/APK_SIGNER/JAVA_SDK/JAVA_COMPILER, etc. */ }
public interface Installable {
    boolean isInstalled(Context);
    void install(Context) throws IOException;
}
  • Les chaînes d'outils personnalisées sont enregistrées dans application.onInit() avec ToolchainService.setTool(customKey, impl).
  • Les clés des chaînes d'outils Android intégrées se trouvent dans l'interface Tool (on peut directement utiliser Platform.getService(TOOLCHAIN).getTool(Tool.AAPT2)).
  • Réutilisation de la chaîne de compilation hôte (méthode du plugin aar/plugin sans installation) : ne pas empaqueter son propre compilateur, mais utiliser getDependencyTaskByName("compileWithTiecodec") pour récupérer la tâche hôte et la lier comme dépendance, ou directement réutiliser getTaskId().

6. Configuration d'exécution : RunConfiguration / TaskRunConfiguration

Ajoute des éléments exécutables au menu « Exécuter » du projet. Le plus courant est TaskRunConfiguration : spécifier un id de tâche, et après l'exécution réussie de la tâche, le callback onResult est appelé.

public class GoStartRunConfig extends TaskRunConfiguration {
    public Project getProject() { return Platform.getProject(); }
    public String getTaskId() { return "RunWithGo"; }          // Id de la tâche associée
    public ProjectVariant getVariant() { return ProjectVariant.DEBUG; }

    @Override
    public void onResult(boolean result, Task task) {
        if (result) {
            // Exécution réussie, lancer le programme
        }
    }

    @Override
    public String getConfigurationName() { return "Exécuter Go"; }
    @Override
    public String getDescription() { return "Compiler et exécuter le programme Go"; }
}

[Le contenu a été tronqué pour la traduction. La compétence continue avec les sections suivantes.]

Skills associés