Skip to content
This repository was archived by the owner on Sep 13, 2025. It is now read-only.

Latest commit

Β 

History

History
121 lines (92 loc) Β· 4.3 KB

File metadata and controls

121 lines (92 loc) Β· 4.3 KB

Short dev overview

1. 🎬 Basics

As mentioned earlier, Patchron knowledge is based upon patches. Patch contains latest changes done to particular file. To understand it better, here is an example of how received data looks like:

"@@ -10,13 +10,7 @@ const payload = require('./fixtures/pull_request.opened');\n" +
" const fs = require('fs');\n" +
" const path = require('path');\n" +
' \n' +
'-const {\n' +
'-    describe,\n' +
'-    expect,\n' +
'-    test,\n' +
"-} = require('@jest/globals');\n" +
"+const { expect, test } = require('@jest/globals');\n" +
' \n' +
'@@ -27,7 +21,6 @@ const deployment = {\n' +
"         schema: 'rocks!',\n" +
'     },\n' +
"     environment: 'production',\n" +
`-    description: "My Probot App's first deploy!",\n` +
' };\n' +

1.1. πŸ†˜ Patch details

If you aren't familiar with patch indicators, here is short explanation:

  • line that was added starts with +
  • line that was removed starts with -
  • line that was unchanged starts with whitespace
  • line that begins with @@ is hunk header. It allows to identify lines in respect to source file. It also informs about hunk length.

Hunk header e.g. @@ -10,13 +10,7 @@ contains following information:

  • LEFT SIDE -10,13
    • 10 is number of first line that starts below hunk header
    • 13 is left side hunk length (sum of unchanged and removed lines)
  • RIGHT SIDE +10,7
    • 10 is number of first line that starts below hunk header
    • 7 is right side hunk length (sum of unchanged and added lines)

2. πŸ”„ Data processing

In all rules that analyze source code, received data is organized via setupData method that "unpacks" patch content into collection. Each object contains information mentioned below:

{
    index: number,
    indentation: number,
    content: string,
    trimmedContent: string
}

Rules that are intended to focus on more than single line of patch are using getMultiLineStructure helper. It allows to pass multiLineOptions array. Each array's object is built in the following manner:

{
    indicator: object|null,       // first line of multi-line
    limiter: object|Array<object> // last line of multi-line
}

For more details on how those objects can be arranged, refer to general type definitions, implementation itself or examples.

3. πŸ’‘ Rule creation

In each rule we can mark out 3 to 4 steps: 1) loading configuration, 2) setting up data (does not refer to pull rules), 3) performing review and 4) returning comments. The things that we need to focus on are:

  • awareness of how file.splitPatch (and data after this.setupData(splitPatch)) looks like
  • concept how to determine case that should be commented out to the PR owner

Once project is forked/pulled, as first step in rule creation, consider pinning to IDE type definitions. To start scratching rule, copy structure from another file implementation or refer to template given below and start coding 🌞 If you prefer to write tests first, feel free to do so πŸ‘

const BaseRule = require('src/rules/Base');

class TemplateRule extends BaseRule {
    /**
     * @param {PatchronContext} patchronContext
     * @param {object} config
     * @param {Patch} file
     */
    constructor(patchronContext, config, file) {
        super(patchronContext, file);

        // 0. load rule config (if needed)
    }

    invoke() {
        const reviewComments = [];

        // 1. setup data (if rule targets patch content)
        const { splitPatch } = this.file;

        const data = this.setupData(splitPatch);

        // 2. determine wrong cases and add comments to array

        // 3. done
        return reviewComments;
    }

    /**
     * @returns {string}
     */
    _getCommentBody(param1, param2) {
        // if comment has complicated markdown structure (like in MarkedCommentsRule) use `dedent-js`
        return '';
    }
}

module.exports = TemplateRule;