doc: generate and edit comments for tools

This commit is contained in:
KernelDeimos 2024-12-06 12:36:35 -05:00
parent c6455d53e4
commit 9aeecb650a
5 changed files with 216 additions and 3 deletions

View File

@ -1,3 +1,4 @@
// METADATA // {"ai-commented":{"service":"claude"}}
/*
* Copyright (C) 2024 Puter Technologies Inc.
*
@ -25,7 +26,13 @@ function reportError(message) {
process.stderr.write(`${message}\n`);
}
// Check that each translation file is recorded in `translations`
/**
* Verifies that all translation files in the translations directory are properly registered
* in the translations object. Checks for required properties like name, code, and dictionary.
* Reports errors if translations are missing, improperly configured, or have mismatched codes.
* @async
* @returns {Promise<void>}
*/
async function checkTranslationRegistrations() {
const files = await fs.promises.readdir('./src/gui/src/i18n/translations');
for (const fileName of files) {
@ -53,7 +60,13 @@ async function checkTranslationRegistrations() {
}
}
// Ensure that translations only contain keys that exist in the en dictionary
/**
* Validates that translation dictionaries only contain keys present in en.js
*
* Iterates through all translations (except English) and checks that each key in their
* dictionary exists in the en.js dictionary. Reports errors for any keys that don't exist.
* Skips validation if the translation dictionary is missing or invalid.
*/
function checkTranslationKeys() {
const enDictionary = translations.en.dictionary;
@ -72,7 +85,15 @@ function checkTranslationKeys() {
}
}
// Ensure that all keys passed to i18n() exist in the en dictionary
/**
* Checks for usage of i18n() calls in source files and verifies that all translation keys exist in en.js
*
* Scans JavaScript files in specified source directories for i18n() function calls using regex.
* Validates that each key used in these calls exists in the English translation dictionary.
*
* @async
* @returns {Promise<void>}
*/
async function checkTranslationUsage() {
const enDictionary = translations.en.dictionary;

View File

@ -1,3 +1,4 @@
// METADATA // {"ai-commented":{"service":"claude"}}
/*
* Copyright (C) 2024 Puter Technologies Inc.
*
@ -44,6 +45,14 @@ lib.dedent_lines = lines => {
}
};
/**
* Creates a StringStream object for parsing a string with position tracking
* @param {string} str - The string to parse
* @param {Object} [options] - Optional configuration object
* @param {Object} [options.state_] - Initial state with position
* @returns {Object} StringStream instance with parsing methods
*/
const StringStream = (str, { state_ } = {}) => {
const state = state_ ?? { pos: 0 };
return {
@ -190,6 +199,13 @@ const BlockCommentParser = ({
};
};
/**
* Creates a writer for line-style comments with a specified prefix
* @param {Object} options - Configuration options
* @param {string} options.prefix - The prefix to use for each comment line
* @returns {Object} A comment writer object
*/
const LinesCommentWriter = ({ prefix }) => {
return {
write: (lines) => {
@ -202,6 +218,15 @@ const LinesCommentWriter = ({ prefix }) => {
};
};
/**
* Creates a block comment writer with specified start/end markers and prefix
* @param {Object} options - Configuration options
* @param {string} options.start - Comment start marker (e.g. "/*")
* @param {string} options.end - Comment end marker (e.g. "* /")
* @param {string} options.prefix - Line prefix within comment (e.g. " * ")
* @returns {Object} Block comment writer object
*/
const BlockCommentWriter = ({ start, end, prefix }) => {
return {
write: (lines) => {
@ -217,6 +242,15 @@ const BlockCommentWriter = ({ start, end, prefix }) => {
};
};
/**
* Creates a new CommentParser instance for parsing and handling source code comments
*
* @returns {Object} An object with methods:
* - supports: Checks if a file type is supported
* - extract_top_comments: Extracts comments from source code
* - output_comment: Formats and outputs comments in specified style
*/
const CommentParser = () => {
const registry_ = {
object: {
@ -263,6 +297,13 @@ const CommentParser = () => {
};
/**
* Gets the language configuration for a given filename by extracting and validating its extension
* @param {Object} params - The parameters object
* @param {string} params.filename - The filename to get the language for
* @returns {Object} Object containing the language configuration
*/
const get_language_by_filename = ({ filename }) => {
const { language } = (({ filename }) => {
const { language_id } = (({ filename }) => {
@ -293,6 +334,13 @@ const CommentParser = () => {
return { language };
}
/**
* Checks if a given filename is supported by the comment parser
* @param {Object} params - The parameters object
* @param {string} params.filename - The filename to check support for
* @returns {boolean} Whether the file type is supported
*/
const supports = ({ filename }) => {
try {
get_language_by_filename({ filename });
@ -338,6 +386,15 @@ const CommentParser = () => {
return results;
}
/**
* Outputs a comment in the specified style for a given filename and text
* @param {Object} params - The parameters object
* @param {string} params.filename - The filename to determine comment style
* @param {string} params.style - The comment style to use ('lines' or 'block')
* @param {string} params.text - The text content of the comment
* @returns {string} The formatted comment string
*/
const output_comment = ({ filename, style, text }) => {
const { language } = get_language_by_filename({ filename });

View File

@ -1,3 +1,4 @@
// METADATA // {"ai-commented":{"service":"claude"}}
/*
* Copyright (C) 2024 Puter Technologies Inc.
*
@ -18,6 +19,7 @@
*/
import { simpleGit } from 'simple-git';
// GitHub repository URL for generating commit links in release notes
const REPO_URL = 'https://github.com/HeyPuter/puter';
const params = {
@ -31,6 +33,7 @@ const git = simpleGit();
const log = await git.log({ from: params.from });
const commits = log.all;
// Array of all commits from git log between specified versions
const CC_REGEX = /^([a-z0-9]+)(\([a-z0-9]+\))?:\s(.*)/;
const parse_conventional_commit = message => {
const parts = CC_REGEX.exec(message);
@ -84,6 +87,10 @@ const scope_aliases = {
};
const complicated_cases = [
/**
* Handles special cases for commit message transformations
* @type {Array<function>}
*/
function fix_i18n ({ commit, meta }) {
if ( meta.type === 'fix' && meta.scope === 'i18n' ) {
meta.type = 'i18n';

View File

@ -1,3 +1,4 @@
// METADATA // {"ai-commented":{"service":"claude"}}
/*
* Copyright (C) 2024 Puter Technologies Inc.
*
@ -29,6 +30,15 @@ const { CommentParser } = require('../comment-parser/main');
const fs = require('fs');
const path_ = require('path');
/**
* Compares two license headers and returns their Levenshtein distance and formatted diff
* @param {Object} params - The parameters object
* @param {string} params.header1 - First header text to compare
* @param {string} params.header2 - Second header text to compare
* @param {boolean} [params.distance_only=false] - If true, only return distance without diff
* @returns {Object} Object containing distance and formatted terminal diff
*/
const CompareFn = ({ header1, header2, distance_only = false }) => {
// Calculate Levenshtein distance
@ -64,6 +74,13 @@ const CompareFn = ({ header1, header2, distance_only = false }) => {
};
}
/**
* Creates a license checker instance that can compare and validate license headers
* @param {Object} params - Configuration parameters
* @param {Object} params.comment_parser - Comment parser instance to use
* @param {string} params.desired_header - The expected license header text
* @returns {Object} License checker instance with compare and supports methods
*/
const LicenseChecker = ({
comment_parser,
desired_header,
@ -197,6 +214,15 @@ const license_check_test = async ({ options }) => {
}
};
/**
* Executes the main command line interface for the license header tool.
* Sets up Commander.js program with commands for checking and syncing license headers.
* Handles configuration file loading and command execution.
*
* @async
* @returns {Promise<void>} Resolves when command execution is complete
*/
const cmd_check_fn = async () => {
const comment_parser = CommentParser();
const license_checker = LicenseChecker({
@ -335,6 +361,18 @@ const cmd_check_fn = async () => {
t.printTable();
};
/**
* Synchronizes license headers in source files by adding missing headers and handling conflicts
*
* Walks through files, checks for license headers, and:
* - Adds headers to files missing them
* - Prompts user to resolve conflicts when headers don't match
* - Handles duplicate headers by allowing removal
* - Tracks counts of different header statuses (ok, missing, conflict, etc)
*
* @returns {Promise<void>} Resolves when synchronization is complete
*/
const cmd_sync_fn = async () => {
const comment_parser = CommentParser();
const desired_header = fs.readFileSync(
@ -547,6 +585,14 @@ const cmd_sync_fn = async () => {
t.printTable();
};
/**
* Main entry point for the license header tool.
* Sets up command line interface using Commander and processes commands.
* Handles 'check' and 'sync' commands for managing license headers in files.
*
* @returns {Promise<void>} Resolves when command processing is complete
*/
const main = async () => {
const { program } = require('commander');
const helptext = dedent(`

View File

@ -1,6 +1,19 @@
// METADATA // {"ai-commented":{"service":"claude"}}
const dedent = require('dedent');
const doctrine = require('doctrine');
/**
* Out class - A utility class for generating formatted text output
* Provides methods for creating headings, line feeds, and text output
*
* ~~with a fluent interface.~~
* ^ Nope, AI got this wrong but maybe it's a good idea to
* make this a fluent interface
*
* The constructor returns a bound function that
* maintains the output state and provides access to helper methods.
*/
class Out {
constructor () {
this.str = '';
@ -15,13 +28,29 @@ class Out {
this.str += '#'.repeat(n) + ' ' + text + '\n\n';
}
/**
* Adds a line feed (newline) to the output string
* @returns {void}
*/
lf () { this.str += '\n'; }
/**
* Append to the string
* @param {string} str
*/
out (str) {
this.str += str;
}
}
/**
* Doc class serves as a base class for documentation generation.
* Provides core functionality for parsing and storing documentation comments
* using the doctrine parser. Contains methods for handling JSDoc-style
* comments and maintaining documentation state.
*/
class Doc {
constructor () {
this._construct();
@ -32,25 +61,52 @@ class Doc {
}
}
/**
* ModuleDoc class extends Doc to represent documentation for a module.
* Handles module-level documentation including services, libraries, and requirements.
* Provides methods for adding services/libraries and generating markdown documentation.
* Tracks external imports and generates notes about module dependencies.
*/
class ModuleDoc extends Doc {
/**
* Initializes the base properties for a ModuleDoc instance
* Sets up empty arrays for services, requires, and libs collections
* @private
*/
_construct () {
this.services = [];
this.requires = [];
this.libs = [];
}
/**
* Creates and adds a new service to this module's services array
* @returns {ServiceDoc} The newly created service document instance
*/
add_service () {
const service = new ServiceDoc();
this.services.push(service);
return service;
}
/**
* Creates and adds a new LibDoc instance to the module's libs array
* @returns {LibDoc} The newly created LibDoc instance
*/
add_lib () {
const lib = new LibDoc();
this.libs.push(lib);
return lib;
}
/**
* Populates a "notes" array for the module documentation
* based on findings about imports.
*/
ready () {
this.notes = [];
const rel_requires = this.requires.filter(r => r.startsWith('../'));
@ -114,7 +170,19 @@ class ModuleDoc extends Doc {
}
}
/**
* ServiceDoc class represents documentation for a service module.
* Handles parsing and formatting of service-related documentation including
* listeners, methods, and their associated parameters. Extends the base Doc class
* to provide specialized documentation capabilities for service components.
*/
class ServiceDoc extends Doc {
/**
* Represents documentation for a service
* Handles parsing and storing service documentation including listeners and methods
* Initializes with empty arrays for listeners and methods
*/
_construct () {
this.listeners = [];
this.methods = [];
@ -206,7 +274,21 @@ class ServiceDoc extends Doc {
}
}
/**
* LibDoc class for documenting library modules
* Handles documentation for library functions including their descriptions,
* parameters, and markdown generation. Extends the base Doc class to provide
* specialized documentation capabilities for library components.
*/
class LibDoc extends Doc {
/**
* Represents documentation for a library module
*
* Handles parsing and formatting documentation for library functions.
* Stores function definitions with their comments, parameters and descriptions.
* Can output formatted markdown documentation.
*/
_construct () {
this.functions = [];
}