<commit_before>// The module 'vscode' contains the VS Code extensibility API
// Import the necessary extensibility types to use in your code below
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';

// This method is called when your extension is activated. Activation is
// controlled by the activation events defined in package.json.
export function activate(context: vscode.ExtensionContext) {
    // System Verilog Hover Provider
    context.subscriptions.push(
        vscode.languages.registerHoverProvider('systemverilog',
            new SystemVerilogHoverProvider()
        )
    );

    // instantiate system verilog module
    context.subscriptions.push(
        vscode.commands.registerCommand('extension.systemverilog.instantiateModule',
            instantiateModuleInteract
        )
    );
}

class SystemVerilogHoverProvider implements vscode.HoverProvider {

    private _excludedText: RegExp;

    constructor() {
        this._excludedText = RegExp(/\b(alias|always|always_comb|always_ff|always_latch|and|assert|assign|assume|automatic|before|begin|bind|bins|binsof|bit|break|buf|bufif0|bufif1|byte|case|casex|casez|cell|chandle|class|clocking|cmos|config|const|constraint|context|continue|cover|covergroup|coverpoint|cross|deassign|default|defparam|design|disable|dist|do|edge|else|end|endcase|endclass|endclocking|endconfig|endfunction|endgenerate|endgroup|endinterface|endmodule|endpackage|endprimitive|endprogram|endproperty|endspecify|endsequence|endtable|endtask|enum|event|expect|export|extends|extern|final|first_match|for|force|foreach|forever|fork|forkjoin|function|generate|genvar|highz0|highz1|if|iff|ifnone|ignore_bins|illegal_bins|import|incdir|include|initial|inout|input|inside|instance|int|integer|interface|intersect|join|join_any|join_none|large|liblist|library|local|localparam|logic|longint|macromodule|matches|medium|modport|module|nand|negedge|new|nmos|nor|noshowcancelled|not|notif0|notif1|null|or|output|package|packed|parameter|pmos|posedge|primitive|priority|program|property|protected|pull0|pull1|pulldown|pullup|pulsestyle_onevent|pulsestyle_ondetect|pure|rand|randc|randcase|randsequence|rcmos|real|realtime|ref|reg|release|repeat|return|rnmos|rpmos|rtran|rtranif0|rtranif1|scalared|sequence|shortint|shortreal|showcancelled|signed|small|solve|specify|specparam|static|string|strong0|strong1|struct|super|supply0|supply1|table|tagged|task|this|throughout|time|timeprecision|timeunit|tran|tranif0|tranif1|tri|tri0|tri1|triand|trior|trireg|type|typedef|union|unique|unsigned|use|uwire|var|vectored|virtual|void|wait|wait_order|wand|weak0|weak1|while|wildcard|wire|with|within|wor|xnor|xor)\b/);
    }

    public provideHover(
        document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
        vscode.Hover {
            // get word start and end
            let textRange = document.getWordRangeAtPosition(position);

            // hover word
            let targetText = document.getText(textRange);

            if (targetText.search(this._excludedText) !== -1) { // systemverilog keywords
                return;
            } else { // find declaration
                let declarationText = this._findDeclaration(document, position, targetText);
                if (declarationText !== undefined) {
                    return new vscode.Hover([ {language: 'systemverilog', value: declarationText.element}, declarationText.comment ]);
                } else {
                    return;
                }
            }
    }

    private _findDeclaration(document: vscode.TextDocument, position: vscode.Position, target: string): {element: string, comment: string} {
        // check target is valid variable name
        if (target.search(/[A-Za-z_][A-Za-z0-9_]*/g) === -1) {
            return;
        }

        let variableType = String.raw`\b(input|output|inout|reg|wire|logic|integer|bit|byte|shortint|int|longint|time|shortreal|real|double|realtime)\b\s+`;
        let variableTypeStart = '^' + variableType;
        let paraType = String.raw`^\b(parameter|localparam)\b\s+\b${target}\b`;

        let regexTarget = RegExp(String.raw`\b${target}\b`);
        let regexVariableType = RegExp(variableType, 'g');
        let regexVariableTypeStart = RegExp(variableTypeStart);
        let regexParaType = RegExp(paraType);

        // from previous line to first line
        for (let i = position.line-1; i >= 0; i--) {
            // text at current line
            let line = document.lineAt(i).text;
            let element = line.replace(/\/\/.*/, '').trim().replace(/\s+/g, ' ');
            let lastChar = element.charAt(element.length - 1);
            if (lastChar === ',' || lastChar === ';') { // remove last ',' or ';'
                element = element.substring(0, element.length - 1);
            }

            // find variable declaration type
            if (element.search(regexVariableTypeStart) !== -1) {
                // replace type to '', like input, output
                let subText = element.replace(regexVariableType, '').trim();

                // replace array to '', like [7:0]
                subText = subText.replace(/(\[.+?\])?/g, '').trim();
                if (subText.search(regexTarget) !== -1) {
                    // Spearate comment after the declaration
                    let comment = undefined;
                    let idx = line.indexOf("//");
                    if(idx !== -1)
                        comment = line.substr(idx + 2).trim();
                    return {element: element, comment: comment};
                }
            }

            // find parameter declaration type
            if (element.search(regexParaType) !== -1) {
                // Spearate comment after the declaration
                let comment = undefined;
                let idx = line.indexOf("//");
                if(idx !== -1)
                    comment = line.substr(idx + 2).trim();
                return { element: element, comment: comment };
            }
        }
    }
}

function getDirectories (srcpath: string): string[] {
    return fs.readdirSync(srcpath)
        .filter(file => fs.statSync(path.join(srcpath, file)).isDirectory());
}

function getFiles (srcpath: string): string[] {
    return fs.readdirSync(srcpath)
        .filter(file => fs.statSync(path.join(srcpath, file)).isFile());
}

function selectFile(currentDir?: string): Thenable<string> {
    currentDir = currentDir || vscode.workspace.rootPath;<commit_msg>Add support ofr prefixed comments in Hover with fallback to suffix<commit_after>// The module 'vscode' contains the VS Code extensibility API
// Import the necessary extensibility types to use in your code below
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';

// This method is called when your extension is activated. Activation is
// controlled by the activation events defined in package.json.
export function activate(context: vscode.ExtensionContext) {
    // System Verilog Hover Provider
    context.subscriptions.push(
        vscode.languages.registerHoverProvider('systemverilog',
            new SystemVerilogHoverProvider()
        )
    );

    // instantiate system verilog module
    context.subscriptions.push(
        vscode.commands.registerCommand('extension.systemverilog.instantiateModule',
            instantiateModuleInteract
        )
    );
}

class SystemVerilogHoverProvider implements vscode.HoverProvider {

    private _excludedText: RegExp;

    constructor() {
        this._excludedText = RegExp(/\b(alias|always|always_comb|always_ff|always_latch|and|assert|assign|assume|automatic|before|begin|bind|bins|binsof|bit|break|buf|bufif0|bufif1|byte|case|casex|casez|cell|chandle|class|clocking|cmos|config|const|constraint|context|continue|cover|covergroup|coverpoint|cross|deassign|default|defparam|design|disable|dist|do|edge|else|end|endcase|endclass|endclocking|endconfig|endfunction|endgenerate|endgroup|endinterface|endmodule|endpackage|endprimitive|endprogram|endproperty|endspecify|endsequence|endtable|endtask|enum|event|expect|export|extends|extern|final|first_match|for|force|foreach|forever|fork|forkjoin|function|generate|genvar|highz0|highz1|if|iff|ifnone|ignore_bins|illegal_bins|import|incdir|include|initial|inout|input|inside|instance|int|integer|interface|intersect|join|join_any|join_none|large|liblist|library|local|localparam|logic|longint|macromodule|matches|medium|modport|module|nand|negedge|new|nmos|nor|noshowcancelled|not|notif0|notif1|null|or|output|package|packed|parameter|pmos|posedge|primitive|priority|program|property|protected|pull0|pull1|pulldown|pullup|pulsestyle_onevent|pulsestyle_ondetect|pure|rand|randc|randcase|randsequence|rcmos|real|realtime|ref|reg|release|repeat|return|rnmos|rpmos|rtran|rtranif0|rtranif1|scalared|sequence|shortint|shortreal|showcancelled|signed|small|solve|specify|specparam|static|string|strong0|strong1|struct|super|supply0|supply1|table|tagged|task|this|throughout|time|timeprecision|timeunit|tran|tranif0|tranif1|tri|tri0|tri1|triand|trior|trireg|type|typedef|union|unique|unsigned|use|uwire|var|vectored|virtual|void|wait|wait_order|wand|weak0|weak1|while|wildcard|wire|with|within|wor|xnor|xor)\b/);
    }

    public provideHover(
        document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
        vscode.Hover {
            // get word start and end
            let textRange = document.getWordRangeAtPosition(position);

            // hover word
            let targetText = document.getText(textRange);

            if (targetText.search(this._excludedText) !== -1) { // systemverilog keywords
                return;
            } else { // find declaration
                let declarationText = this._findDeclaration(document, position, targetText);
                if (declarationText !== undefined) {
                    return new vscode.Hover([ {language: 'systemverilog', value: declarationText.element}, declarationText.comment ]);
                } else {
                    return;
                }
            }
    }

    private _findDeclaration(document: vscode.TextDocument, position: vscode.Position, target: string): {element: string, comment: string} {
        // check target is valid variable name
        if (target.search(/[A-Za-z_][A-Za-z0-9_]*/g) === -1) {
            return;
        }

        let variableType = String.raw`\b(input|output|inout|reg|wire|logic|integer|bit|byte|shortint|int|longint|time|shortreal|real|double|realtime)\b\s+`;
        let variableTypeStart = '^' + variableType;
        let paraType = String.raw`^\b(parameter|localparam)\b\s+\b${target}\b`;

        let regexTarget = RegExp(String.raw`\b${target}\b`);
        let regexVariableType = RegExp(variableType, 'g');
        let regexVariableTypeStart = RegExp(variableTypeStart);
        let regexParaType = RegExp(paraType);

        // from previous line to first line
        for (let i = position.line-1; i >= 0; i--) {
            // text at current line
            let line = document.lineAt(i).text;
            let element = line.replace(/\/\/.*/, '').trim().replace(/\s+/g, ' ');
            let lastChar = element.charAt(element.length - 1);
            if (lastChar === ',' || lastChar === ';') { // remove last ',' or ';'
                element = element.substring(0, element.length - 1);
            }

            // find variable declaration type
            if (element.search(regexVariableTypeStart) !== -1) {
                // replace type to '', like input, output
                let subText = element.replace(regexVariableType, '').trim();

                // replace array to '', like [7:0]
                subText = subText.replace(/(\[.+?\])?/g, '').trim();
                if (subText.search(regexTarget) !== -1) {
                    let comment = getPrefixedComment(document, i);
                    if (comment)
                        return { element: element, comment: comment };
                    else {
                        comment = getSuffixedComment(document, i);
                        return { element: element, comment: comment };
                    }
                }
            }

            // find parameter declaration type
            if (element.search(regexParaType) !== -1) {
                let comment = getPrefixedComment(document, i);
                if(comment)
                    return { element: element, comment: comment };
                else{
                    comment = getSuffixedComment(document, i);
                    return { element: element, comment: comment };
                }
            }
        }
    }
}

function getPrefixedComment(document: vscode.TextDocument, lineNo: number) {
    let i = lineNo - 1;
    let buf = '';
    while (true) {
        let line = document.lineAt(i).text.trim();
        if (!line.startsWith('//'))
            break;
        buf = line.substring(3) + '\n' + buf;
        i--;
    }
    return buf;
}

function getSuffixedComment(document: vscode.TextDocument, lineNo: number) : string {
    // Spearate comment after the declaration
    let line = document.lineAt(lineNo).text;
    let idx = line.indexOf("//");
    if(idx !== -1)
        return line.substr(idx + 2).trim();
    else
        return undefined;
}

function getDirectories (srcpath: string): string[] {
    return fs.readdirSync(srcpath)
        .filter(file => fs.statSync(path.join(srcpath, file)).isDirectory());
}

function getFiles (srcpath: string): string[] {
    return fs.readdirSync(srcpath)
        .filter(file => fs.statSync(path.join(srcpath, file)).isFile());
}

function selectFile(currentDir?: string): Thenable<string> {
    currentDir = currentDir || vscode.workspace.rootPath;
{'fraction_non_alphanumeric': 0.12453841141119397, 'fraction_numerical': 0.005502860039099269, 'mean_word_length': 3.075538506934199, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6565043', 'n_tokens_mistral': 4157, 'n_tokens_neox': 4013, 'n_words': 693}