Skip to main content

Typescript

Hook for transforming code in TypeScript

plugin.yaml
schema-version: v3
kind: plugin
metadata:
name: code-transformation-plugin
display-name: code-transformation-plugin
description: Code transformation example.
version: 1.0.0
spec:
hooks:
- type: code-transformation
engine-version: 0.2.0-beta
trigger: after-render
language: typescript
trans-pattern-path: trans-patterns/pattern.ts
source-path: src/code.ts

Statement

The transformation engine supports constructs called statements. A statement is a language command that produces a side effect and does not result in a value. This is the most common type of construct in TypeScript. Here are some examples of statuses:

  • import command
  • export command
  • variable declaration
  • function declaration
  • arrow function declaration
  • generator declaration
  • class declaration
  • enum declaration
  • interface declaration
  • namespace declaration
  • function call
  • method call
  • variable assignment
  • decision commands (if and switch)
  • iteration commands (for, while, and do-while)
  • return, yield, break, and continue commands
  • with command
  • try command

In any valid part of the language where one of these statements may occur, you can use the transformation operators in the transformation pattern you are creating. For example:

Transformation pattern using operators only in statement constructions
<<<< patter-name: my-pattern-name; pattern-scope: file-scope; >>>>

<...>
import MyClass from './Myclass';
+<import MyClass2 from 'MyClass2';>+

<...>

function print_message(message:string):void{
+<if (message === null || message === undefined) {
throw new Error("The string is null or undefined");
}>+
console.log('MESSAGE: ' + message);
}

let message: string = 'My Message';
print_message(message);

<...>

-<message = 'My Message 2';>-
-<print_message(message);>-

<...>

const myClassInstance = new MyClass();
+<const myClass2Instance = new MyClass2();>+

+<class MyClass3 {

myMethod(): string {
return "My Method";
}
}>+

+<const myClass3Instance = new MyClass3();>+
+<print_message(myClass3Instance.myMethod());>+
<...>

In the previous transformation pattern example, several ellipsis operators are used to replace statements in parts of the code.

  • In line 3, an operator inserts an import statement.
  • From line 8 to line 10, an operator inserts an if statement in the body of a function.
  • In lines 19 and 20, each operator removes an assignment and function call statements, respectively.
  • In line 25, an operator inserts a variable declaration statement.
  • From line 27 to line 32, an operator inserts a class declaration.
  • In line 34, an operator inserts a variable declaration.
  • Finally, in line 35, an operator inserts a function call.

Class element

Class elements are constructs supported by the transformation engine. A class element is a declaration within the body of a class. See below some examples of class elements:

  • method declaration
  • declaration of ownership
  • constructor declaration

In any valid part of the language where one of these class elements may occur, you can use the transformation operators in the transformation pattern you have created. Example:

Transformation pattern using operators only in class element constructions
<<<< patter-name: my-pattern-name; pattern-scope: file-scope; >>>>

<...>
class MyClass {
+<myprop:string = "";>+

<...>

myMethod1(): string {
<...>
}

<...>

+<myMethod2(): string {
return "Executed myMethod2";
}>+
}
<...>

In the previous transformation pattern example, you can observe several ellipsis operators used in parts of the code to replace class elements.

  • In line 3, an operator inserts a property class element as the first element of the MyClass class.
  • From line 13 to line 15, an operator inserts a method declaration class element as the last element of the MyClass class.

Examples of advanced transformation patterns

tip

To simplify creating your script using transformation patterns, duplicate the original file you want to transform and make the necessary edits with the desired patterns.

Examples of creating complex transformation patterns to transform source code are provided below. The examples demonstrate the files in their original state, the transformation pattern, and the original transformed file.

1. Example of ellipsis and insertion operators

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}

2. Example of ellipsis and removal operators

import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnInit {

public greeting: string = 'Hello World!';
public counter: number = 0;

constructor() {}

ngOnInit(): void {}

public incrementCounter(): void {
this.counter++;
}
}

3. Example with all ellipsis, insertion, and removal operators

import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';

@Component({
selector: 'app-example',
template: '<div>{{ data }}</div>',
styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {
data: string;

constructor(private dataService: DataService) { }

ngOnInit(): void {
this.data = this.dataService.getData();
}
}

4. Example with ID Match and String Match Operators

app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { MyComponentA } from './my-component-a/my-component-a.component';
import { MyComponentB } from './my-component-b/my-component-b.component';
import { MyComponentC } from './my-component-c/my-component-c.component';

@NgModule({
declarations: [
AppComponent,
MyComponentA,
MyComponentB,
MyComponentC
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }