Asper Header  1.0.14
The header injector extension
Loading...
Searching...
No Matches
commentGenerator.ts
Go to the documentation of this file.
1
59import * as vscode from 'vscode';
60import { minimatch } from 'minimatch';
61import { CodeConfig, CodeConfigType } from './processConfiguration';
62import { query } from './querier';
63import { logger } from './logger';
64import { getMessage } from './messageProvider';
65import { LazyFileLoader } from './lazyFileLoad';
66import { RandomLogo, logo } from './randomLogo';
67
75interface CommentStyle {
77 singleLine: string[];
79 multiLine: string[];
81 prompt_comment_opening_type: boolean;
82}
83
135export class CommentGenerator {
137 private Config: CodeConfigType = CodeConfig;
139 private randomLogo: RandomLogo = new RandomLogo();
141 private languageComment: LazyFileLoader | undefined = undefined;
143 private documentBody: vscode.TextDocument | undefined = undefined;
145 private filePath: string | undefined = undefined;
147 private fileName: string | undefined = undefined;
149 private fileExtension: string | undefined = undefined;
151 private languageId: string | undefined = undefined;
153 private documentEOL: vscode.EndOfLine | undefined = undefined;
155 private documentVersion: number | undefined = undefined;
157 private headerInnerStart: number | undefined = undefined;
159 private headerInnerEnd: number | undefined = undefined;
161 private maxScanLength: number = this.Config.get("maxScanLength");
163 private headerLogo: string[] = this.Config.get("headerLogo");
165 private projectName: string = this.Config.get("extensionName");
167 private projectCopyRight: string = this.Config.get("projectCopyright");
169 private addBlankLineAfterMultiline: boolean = this.Config.get("headerAddBlankLineAfterMultiline");
170
180 constructor(languageComment: LazyFileLoader | undefined = undefined, editor: vscode.TextEditor | undefined = undefined, randomLogoInstance: RandomLogo | undefined = undefined) {
181 logger.debug(getMessage("inFunction", "constructor", "CommentGenerator"));
182 if (languageComment !== undefined) {
183 this.languageComment = languageComment;
184 logger.debug(getMessage("foundLanguageComment"));
185 } else {
186 logger.warning(getMessage("missingLanguageComment"));
187 }
188 if (!editor) {
189 logger.warning(getMessage("noFocusedEditors"));
190 } else {
191 this.updateFileInfo(editor);
192 logger.debug(getMessage("foundFocusEditor"));
193 }
194 if (!randomLogoInstance) {
195 logger.warning(getMessage("noLogoInstanceProvided"));
196 } else {
197 this.randomLogo = randomLogoInstance;
198 logger.debug(getMessage("foundLogoInstance"));
199 }
200 }
201
210 private determineNewLine(eol: vscode.EndOfLine): string {
211 logger.debug(getMessage("inFunction", "determineNewLine", "CommentGenerator"));
212 if (eol === vscode.EndOfLine.LF) {
213 logger.debug(getMessage("foundNewLine", "\\n"));
214 return "\n";
215 } else {
216 logger.debug(getMessage("foundNewLine", "\\r\\n"));
217 return "\r\n";
218 }
219 }
220
231 private headerOpener(comment: string, eol: vscode.EndOfLine, projectName: string = this.Config.get("extensionName")): string {
232 logger.debug(getMessage("inFunction", "headerOpener", "CommentGenerator"));
233 let final: string = comment + this.Config.get("headerOpenerDecorationOpen");
234 final += this.Config.get("telegraphBegin") + " ";
235 final += projectName;
236 final += this.Config.get("headerOpenerDecorationClose");
237 final += this.determineNewLine(eol);
238 return final;
239 }
240
249 private async determineCorrectComment(): Promise<CommentStyle> {
250 logger.debug(getMessage("inFunction", "determineCorrectComment", "CommentGenerator"));
251 const primaryKey: string = "langs";
252 let commentStructure: CommentStyle = {
253 singleLine: [],
254 multiLine: [],
255 prompt_comment_opening_type: false,
256 };
257 if (this.languageComment === undefined) {
258 logger.Gui.error(getMessage("missingFileError"));
259 return commentStructure;
260 }
261 const jsonContent = await this.languageComment?.get();
262 // logger.info(getMessage("jsonContent", JSON.stringify(jsonContent)));
263 if (!jsonContent || typeof jsonContent !== 'object' || jsonContent === null || (primaryKey in jsonContent) === false) {
264 logger.Gui.error(getMessage("unknownFileStructure"));
265 return commentStructure;
266 }
267 if (Array.isArray(jsonContent[primaryKey]) === false) {
268 logger.Gui.error(getMessage("unknownFileStructure"));
269 return commentStructure;
270 }
271 let index = 0;
272 const languageNodes = jsonContent[primaryKey];
273 let locatedName: string = "";
274 for (; index < languageNodes.length; index++) {
275 let nodeFound = false;
276 const node = languageNodes[index];
277
278 const nodeLangs: string[] = node.langs ?? [];
279 const nodeFileExtensions: Record<string, string[]> = node.fileExtensions ?? {};
280
281 for (let langIndex = 0; langIndex < nodeLangs.length; langIndex++) {
282 const langName = nodeLangs[langIndex].toLowerCase();
283 locatedName = langName;
284
285 if (langName === this.languageId?.toLowerCase()) {
286 nodeFound = true;
287 break;
288 }
289
290 if (this.fileExtension) {
291 const extensionsForLang = nodeFileExtensions[langName] ?? [];
292 for (let extIndex = 0; extIndex < extensionsForLang.length; extIndex++) {
293 let dot: string = "";
294 if (extensionsForLang[extIndex].length > 0 && extensionsForLang[extIndex][0] === ".") {
295 dot = ".";
296 }
297 if (extensionsForLang[extIndex] === `${dot}${this.fileExtension}`) {
298 nodeFound = true;
299 break;
300 }
301 }
302 }
303
304 if (nodeFound) {
305 break;
306 }
307 }
308
309 logger.debug(getMessage("arrayNodeContent", `Json[${primaryKey}]`, index, node));
310 if (nodeFound) {
311 logger.Gui.info(getMessage("identifiedLanguage", locatedName));
312 logger.info(getMessage("arrayNodeContent", `Json[${primaryKey}]`, index, node));
313 commentStructure.singleLine = node.singleLine ?? [];
314 commentStructure.multiLine = node.multiLine ?? [];
315 commentStructure.prompt_comment_opening_type = node.prompt_comment_opening_type ?? false;
316 return commentStructure;
317 }
318 }
319 logger.error(getMessage("languageNotFound", String(this.languageId), this.fileExtension));
320 return commentStructure;
321 }
322
330 private async determineHeaderDescription(): Promise<string[]> {
331 logger.debug(getMessage("inFunction", "determineHeaderDescription", "CommentGenerator"));
332 let final: string[] = [];
333 const usrProjectDescription: string = this.Config.get("projectDescription");
334 if (usrProjectDescription.length === 0) {
335 const usrResponse: string | undefined = await query.input(getMessage("getHeaderDescription"));
336 final.push(usrResponse || "");
337 } else {
338 logger.debug(getMessage("configDescriptionUsed"));
339 final.push(usrProjectDescription);
340 }
341 return final;
342 }
343
351 private async determineHeaderTags(): Promise<string[]> {
352 logger.debug(getMessage("inFunction", "determineHeaderTags", "CommentGenerator"));
353 let final: string[] = [];
354 const usrResponse: string | undefined = await query.input(getMessage("getHeaderTags"));
355 final.push(usrResponse || "");
356 return final;
357 }
358
366 private async determineHeaderPurpose(): Promise<string[]> {
367 logger.debug(getMessage("inFunction", "determineHeaderPurpose", "CommentGenerator"));
368 let final: string[] = [];
369 const usrResponse: string | undefined = await query.input(getMessage("getHeaderPurpose"));
370 final.push(usrResponse || "");
371 return final;
372 }
373
384 private async getSingleCommentOption(commentOptions: string[]): Promise<string> {
385 logger.debug(getMessage("inFunction", "getSingleCommentOption", "CommentGenerator"));
386 if (commentOptions.length === 0) {
387 logger.Gui.error(getMessage("noCommentToShow"));
388 throw Error(getMessage("noCommentToShow"));
389 }
390 if (commentOptions.length === 1) {
391 logger.info(getMessage("noProvidedCommentOptions"));
392 return commentOptions[0];
393 }
394 const response: string | undefined = await query.quickPick(commentOptions, getMessage("chooseSingleLineCommentOption"));
395 return response || commentOptions[0];
396 }
397
405 private addKeyDefinitionSeparator(): string {
406 logger.debug(getMessage("inFunction", "addKeyDefinitionSeparator", "CommentGenerator"));
407 const userSettingDefinedElement: string = this.Config.get("headerKeyDefinitionSeparator");
408 return userSettingDefinedElement || this.Config.get("headerKeyDefinitionSeparator");
409 }
410
420 private addCreationDate(comment: string, eol: vscode.EndOfLine) {
421 logger.debug(getMessage("inFunction", "addCreationDate", "CommentGenerator"));
422 const now = new Date();
423 const day = String(now.getDate()).padStart(2, "0");
424 const month = String(now.getMonth() + 1).padStart(2, "0"); // Months are 0-based
425 const year = now.getFullYear();
426 const separatorDay: string = this.Config.get("headerDateSeperatorDay");
427 const separatorMonth: string = this.Config.get("headerDateSeperatorMonth");
428 const separatorYear: string = this.Config.get("headerDateSeperatorYear");
429 let final: string = comment + this.Config.get("headerCreationDateKey") + this.addKeyDefinitionSeparator();
430 final += `${day}${separatorDay}${month}${separatorMonth}${year}${separatorYear}`;
431 final += this.determineNewLine(eol);
432 return final;
433 }
434
445 private addLastModifiedDate(comment: string, eol: vscode.EndOfLine) {
446 logger.debug(getMessage("inFunction", "addLastModifiedDate", "CommentGenerator"));
447 const now: Date = new Date();
448 const day: string = String(now.getDate()).padStart(2, "0");
449 const month: string = String(now.getMonth() + 1).padStart(2, "0"); // Months are 0-based
450 const year: number = now.getFullYear();
451 const hour: number = now.getHours();
452 const minute: number = now.getMinutes();
453 const seconds: number = now.getSeconds();
454 const separatorDay: string = this.Config.get("headerDateSeperatorDay");
455 const separatorMonth: string = this.Config.get("headerDateSeperatorMonth");
456 const separatorYear: string = this.Config.get("headerDateSeperatorYear");
457 const separatorTimeAndDate: string = this.Config.get("headerTimeAndDateSeperator");
458 const separatorSecond: string = this.Config.get("headerTimeSeperatorSecond");
459 const separatorMinute: string = this.Config.get("headerTimeSeperatorMinute");
460 const separatorHour: string = this.Config.get("headerTimeSeperatorHour");
461 let final: string = comment + this.Config.get("headerLastModifiedKey") + this.addKeyDefinitionSeparator();
462 final += `${hour}${separatorHour}${minute}${separatorMinute}${seconds}${separatorSecond}${separatorTimeAndDate}${day}${separatorDay}${month}${separatorMonth}${year}${separatorYear}`;
463 final += this.determineNewLine(eol);
464 return final;
465 }
466
479 private addMultilineKey(comment: string, eol: vscode.EndOfLine, tagName: string, tagDefinition: string[]): string {
480 logger.debug(getMessage("inFunction", "addMultilineKey", "CommentGenerator"));
481 const eolStr: string = this.determineNewLine(eol);
482 let final: string = comment + tagName + this.addKeyDefinitionSeparator() + eolStr;
483 for (let i = 0; i < tagDefinition.length; i++) {
484 final += comment + tagDefinition[i] + eolStr;
485 }
486 final += comment + this.Config.get("telegraphBlockStop") + eolStr;
487 if (this.addBlankLineAfterMultiline) {
488 final += comment + eolStr;
489 }
490 return final;
491 }
492
503 private addSingleLineKey(comment: string, eol: vscode.EndOfLine, tagName: string, tagDefinition: string): string {
504 logger.debug(getMessage("inFunction", "addSingleLineKey", "CommentGenerator"));
505 let final: string = comment + tagName + this.addKeyDefinitionSeparator();
506 final += tagDefinition + this.determineNewLine(eol);
507 return final;
508 }
509
519 private beforeHeaderCloser(comment: string, eol: vscode.EndOfLine): string {
520 logger.debug(getMessage("inFunction", "beforeHeaderCloser", "CommentGenerator"));
521 return comment + this.Config.get("telegraphEndOfTransmission") + this.determineNewLine(eol);
522 }
523
534 private headerCloser(comment: string, eol: vscode.EndOfLine, projectName: string = this.Config.get("extensionName")): string {
535 logger.debug(getMessage("inFunction", "headerCloser", "CommentGenerator"));
536 let final: string = comment + this.Config.get("headerOpenerDecorationOpen");
537 final += this.Config.get("telegraphEnd") + " ";
538 final += projectName;
539 final += this.Config.get("headerOpenerDecorationClose");
540 final += this.determineNewLine(eol);
541 return final;
542 }
543
553 private updateFileInfo(editor: vscode.TextEditor, document: vscode.TextDocument | undefined = undefined) {
554 logger.debug(getMessage("inFunction", "updateFileInfo", "CommentGenerator"));
555 this.headerInnerEnd = undefined;
556 this.headerInnerStart = undefined;
557 if (document === undefined) {
558 this.documentBody = editor.document;
559 } else {
560 this.documentBody = document;
561 }
562 if (this.Config.get("useWorkspaceNameWhenAvailable")) {
563 this.projectName = this.Config.get("workspaceName") || this.Config.get("extensionName");
564 } else {
565 this.projectName = this.Config.get("extensionName");
566 }
567 this.filePath = this.documentBody.uri.fsPath;
568 this.projectCopyRight = this.Config.get("projectCopyright");
569 this.addBlankLineAfterMultiline = this.Config.get("headerAddBlankLineAfterMultiline");
570 this.maxScanLength = this.Config.get("defaultMaxScanLength") + this.headerLogo.length;
571 this.fileName = this.documentBody.uri.path.split('/').pop() || "unknown";
572 if (this.fileName.includes('.')) {
573 this.fileExtension = this.fileName.split('.').pop() || "none";
574 } else {
575 this.fileExtension = "none";
576 };
577 this.languageId = this.documentBody.languageId;
578 this.documentEOL = this.documentBody.eol;
579 this.documentVersion = this.documentBody.version;
580 }
581
591 private async getCorrectCommentPrefix(determinedComment: CommentStyle): Promise<string[]> {
592 logger.debug(getMessage("inFunction", "getCorrectPrefix", "CommentGenerator"));
593 let commentOpener: string = "";
594 let commentMiddle: string = "";
595 let commentCloser: string = "";
596 if (determinedComment.multiLine.length >= 2) {
597 commentOpener = determinedComment.multiLine[0];
598 if (determinedComment.multiLine.length >= 3) {
599 commentMiddle = determinedComment.multiLine[1];
600 commentCloser = determinedComment.multiLine[2];
601 } else {
602 commentMiddle = "";
603 commentCloser = determinedComment.multiLine[1];
604 }
605 } else if (determinedComment.singleLine.length > 0) {
606 if (determinedComment.prompt_comment_opening_type) {
607 // Ask the user for the type to use based on the single comments that are present.
608 const commentString: string = await this.getSingleCommentOption(determinedComment.singleLine);
609 commentOpener = commentString;
610 commentMiddle = commentString;
611 commentCloser = commentString;
612 } else {
613 commentOpener = determinedComment.singleLine[0];
614 commentMiddle = determinedComment.singleLine[0];
615 commentCloser = determinedComment.singleLine[0];
616 }
617 } else {
618 commentOpener = "";
619 commentMiddle = "";
620 commentCloser = "";
621 }
622 commentOpener += this.Config.get("headerCommentSpacing");
623 commentMiddle += this.Config.get("headerCommentSpacing");
624 commentCloser += this.Config.get("headerCommentSpacing");
625 return [commentOpener, commentMiddle, commentCloser];
626 }
627
643 private async buildTheHeader(comments: string[]): Promise<string[]> {
644 logger.debug(getMessage("inFunction", "buildTheHeader", "CommentGenerator"));
645 const eol: vscode.EndOfLine = this.documentEOL || vscode.EndOfLine.LF;
646 const unknownTerm: string = getMessage("unknown");
647 const commentOpener: string = comments[0] || "";
648 const commentMiddle: string = comments[1] || "";
649 const commentCloser: string = comments[2] || "";
650 let buildHeader: string[] = [];
651 // Preparing the header content so that it can be put in a comment and written.
652 if (commentOpener.length > 0) {
653 buildHeader.push(`${commentOpener}${this.determineNewLine(eol)}`);
654 }
655 // Opening the header
656 buildHeader.push(this.headerOpener(commentMiddle, eol, this.projectName));
657 // The logo
658 let logoContent = this.headerLogo;
659 if (this.Config.get("randomLogo") === true) {
660 try {
661 const gatheredLogo: logo = await this.randomLogo.getRandomLogoFromFolder();
662 if (gatheredLogo.logoContent !== undefined) {
663 logoContent = gatheredLogo.logoContent;
664 } else {
665 logger.error(getMessage("randomLogoGatheringFailed", getMessage("ramdomLogoGatheringLogoUndefined")));
666 }
667 } catch (e) {
668 logger.error(getMessage("randomLogoGatheringFailed", String(e)));
669 }
670 }
671 buildHeader.push(this.addMultilineKey(commentMiddle, eol, this.Config.get("headerLogoKey"), logoContent));
672 // The project name
673 buildHeader.push(this.addSingleLineKey(commentMiddle, eol, this.Config.get("headerProjectKey"), this.projectName));
674 // The file name
675 buildHeader.push(this.addSingleLineKey(commentMiddle, eol, this.Config.get("headerFileKey"), this.fileName || unknownTerm));
676 // The Creation date
677 buildHeader.push(this.addCreationDate(commentMiddle, eol));
678 // The Last modified date
679 buildHeader.push(this.addLastModifiedDate(commentMiddle, eol));
680 // The description
681 buildHeader.push(this.addMultilineKey(commentMiddle, eol, this.Config.get("headerDescriptionKey"), await this.determineHeaderDescription()));
682 // The copyright
683 buildHeader.push(this.addSingleLineKey(commentMiddle, eol, this.Config.get("headerCopyrightKey"), this.projectCopyRight));
684 // The Tag
685 // buildHeader.push(this.addSingleLineKey(commentMiddle, eol, this.Config.get("headerTagKey"), (await this.determineHeaderTags()).join(",")));
686 // The Purpose
687 buildHeader.push(this.addSingleLineKey(commentMiddle, eol, this.Config.get("headerPurposeKey"), (await this.determineHeaderPurpose()).join(";")));
688 // End of transmission telegraph
689 buildHeader.push(this.beforeHeaderCloser(commentMiddle, eol));
690 // Closing the header
691 buildHeader.push(this.headerCloser(commentMiddle, eol, this.projectName));
692 if (commentCloser.length > 0) {
693 buildHeader.push(`${commentCloser}${this.determineNewLine(eol)}`);
694 }
695 return buildHeader;
696 }
697
707 private async updateEditDate(editor: vscode.TextEditor, comments: string[]) {
708 logger.debug(getMessage("inFunction", "updateEditDate", "CommentGenerator"));
709 const commentOpener: string = comments[0] || "";
710 const commentMiddle: string = comments[1] || "";
711 const commentCloser: string = comments[2] || "";
712 if (this.headerInnerStart === undefined || this.headerInnerEnd === undefined) {
713 const errMsg: string = getMessage("updateEditDateMissingBounds");
714 logger.error(errMsg);
715 logger.Gui.error(errMsg);
716 return;
717 }
718 if (!this.documentBody) {
719 const errMsg: string = getMessage("emptyDocument");
720 logger.error(errMsg);
721 logger.Gui.error(errMsg);
722 return;
723 }
724
725 const eol = this.documentEOL || vscode.EndOfLine.LF;
726 const lastModifiedKey = this.Config.get("headerLastModifiedKey");
727
728 // Build the new "Last Modified" line
729 const newLine = this.addLastModifiedDate(commentMiddle, eol).trimEnd();
730
731 let targetLine: number | undefined = undefined;
732
733 // Scan header block to locate the "Last Modified" line
734 for (let i = this.headerInnerStart; i <= this.headerInnerEnd; i++) {
735 const lineText = this.documentBody.lineAt(i).text;
736 if (lineText.includes(lastModifiedKey)) {
737 targetLine = i;
738 break;
739 }
740 }
741
742 if (targetLine === undefined) {
743 const errMsg: string = getMessage("lastModifiedLineNotFound");
744 logger.error(errMsg);
745 logger.Gui.error(errMsg);
746 return;
747 }
748
749 await editor.edit(editBuilder => {
750 const range = this.documentBody!.lineAt(targetLine!).range;
751 editBuilder.replace(range, newLine);
752 });
753
754 const msg: string = getMessage("lastModifiedUpdated");
755 logger.info(msg);
756 logger.Gui.info(msg);
757 }
758
768 protected locateIfHeaderPresent(comments: string[]): boolean | undefined {
769 logger.debug(getMessage("inFunction", "locateIfHeaderPresent", "CommentGenerator"));
770 const commentOpener: string = comments[0] || "";
771 const commentMiddle: string = comments[1] || "";
772 const commentCloser: string = comments[2] || "";
773 this.headerInnerStart = undefined;
774 this.headerInnerEnd = undefined;
775 if (this.documentBody === undefined) {
776 logger.error(getMessage("emptyDocument"));
777 return undefined;
778 }
779 if (this.documentBody.isClosed) {
780 logger.warning(getMessage("closedDocument"));
781 return undefined;
782 }
783 const eol: vscode.EndOfLine = this.documentEOL ?? vscode.EndOfLine.LF;
784 const opener: string = this.headerOpener(commentMiddle, eol, this.projectName);
785 const closer: string = this.headerCloser(commentMiddle, eol, this.projectName);
786 const scanLines: number = Math.min(this.maxScanLength, this.documentBody.lineCount);
787 let lineOpenerFound: boolean = false;
788 let lineCloserFound: boolean = false;
789 for (let i = 0; i < scanLines; i++) {
790 const lineText = this.documentBody.lineAt(i).text;
791 if (lineText === opener.trimEnd() && lineCloserFound) {
792 logger.Gui.warning(getMessage("brokenHeader"));
793 return false;
794 }
795 if (lineText === closer.trimEnd() && !lineOpenerFound) {
796 logger.Gui.warning(getMessage("brokenHeader"));
797 return false;
798 }
799 if (lineText === opener.trimEnd() && (!lineCloserFound && !lineOpenerFound)) {
800 lineOpenerFound = true;
801 this.headerInnerStart = i;
802 logger.info(getMessage("headerOpenerFound"));
803 continue;
804 }
805 if (lineText === closer.trimEnd() && (!lineCloserFound && lineOpenerFound)) {
806 this.headerInnerEnd = i;
807 logger.info(getMessage("headerOpenerAndCloserFound"));
808 return true;
809 }
810 }
811 logger.Gui.warning(getMessage("documentLineScanExceeded", this.maxScanLength));
812 return false;
813 }
814
824 private async writeHeaderToFile(editor: vscode.TextEditor, comments: string[]): Promise<number> {
825 logger.debug(getMessage("inFunction", "writeHeaderToFile", "CommentGenerator"));
826 let offset: number = 0;
827 const headerContent: string[] = await this.buildTheHeader(comments);
828 // determine if the first line has a shebang like line on the first line, if true, add a new line, and write from that line.
829 const headerString: string = headerContent.join("");
830 await editor.edit(editBuilder => editBuilder.insert(new vscode.Position(offset, 0), headerString));
831 return this.Config.get("statusSuccess");
832 }
844 async injectHeader() {
845 logger.debug(getMessage("inFunction", "injectHeader", "CommentGenerator"));
846 const editor = vscode.window.activeTextEditor;
847 if (editor === undefined) {
848 logger.error(getMessage("noFocusedEditors"));
849 logger.Gui.error(getMessage("openFileToApplyHeader"));
850 return;
851 }
852 this.updateFileInfo(editor);
853 // Checking that the meta data is filled out.
854 if (
855 this.documentBody === undefined || this.filePath === undefined
856 || this.fileName === undefined || this.fileExtension === undefined
857 || this.languageId === undefined || this.documentEOL === undefined
858 || this.documentVersion === undefined
859 ) {
860 logger.error(getMessage("corruptedFileMetaData"));
861 logger.Gui.error(getMessage("errorDuringFunctionCall", "injectHeader"));
862 return;
863 }
864 // Making sure that the target document is still open.
865 if (this.documentBody.isClosed) {
866 logger.warning(getMessage("closedDocument"));
867 logger.Gui.warning(getMessage("updateAbortedBecauseFileClosedSyncCancelled"));
868 return;
869 }
870 // Some logging
871 const msg = getMessage("inputArgs", JSON.stringify(this.documentBody), JSON.stringify(this.filePath), JSON.stringify(this.fileName), JSON.stringify(this.fileExtension), JSON.stringify(this.languageId), JSON.stringify(this.documentEOL), JSON.stringify(this.documentVersion));
872 logger.Gui.debug(msg);
873 logger.debug(msg);
874 // Determining the correct comment prefix
875 const determineComment: CommentStyle = await this.determineCorrectComment();
876 const comments: string[] = await this.getCorrectCommentPrefix(determineComment);
877 // attempt to locate the header
878 let response: boolean | undefined = this.locateIfHeaderPresent(comments);
879 if (response === undefined) {
880 logger.Gui.warning(getMessage("updateAbortedBecauseFileClosedSyncCancelled"));
881 return;
882 }
883 if (response === true) {
884 logger.Gui.info(getMessage("updatingEditionDate"));
885 await this.updateEditDate(editor, comments);
886 return;
887 }
888 if (response === false) {
889 let status: number = await this.writeHeaderToFile(editor, comments);
890 if (status === this.Config.get("statusError")) {
891 logger.Gui.error(getMessage("headerWriteFailed"));
892 return;
893 }
894 logger.Gui.info(getMessage("headerWriteSuccess"));
895 }
896 }
897
906 private async allowedToActivate(): Promise<boolean> {
907 logger.debug(getMessage("inFunction", "allowedToActivate", "CommentGenerator"));
908 const ignored: string[] = CodeConfig.get("extensionIgnore") ?? [];
909
910 for (const pattern of ignored) {
911 if (
912 this.fileExtension && minimatch(this.fileExtension, pattern) ||
913 this.fileName && minimatch(this.fileName, pattern) ||
914 this.filePath && minimatch(this.filePath, pattern)
915 ) {
916 return false;
917 }
918 }
919
920 return true;
921 }
922
931 updateLogoInstanceRandomiser(randomLogoInstance: RandomLogo): void {
932 logger.debug(getMessage("inFunction", "updateLogoInstanceRandomiser", "CommentGenerator"));
933 this.randomLogo = randomLogoInstance;
934 }
935
946 async refreshHeader(document: vscode.TextDocument | undefined) {
947 logger.debug(getMessage("inFunction", "refreshHeader", "CommentGenerator"));
948 const refreshOnSave: boolean = CodeConfig.get("refreshOnSave");
949 const promptToCreateIfMissing: boolean = CodeConfig.get("promptToCreateIfMissing");
950 if (!refreshOnSave) {
951 return;
952 }
953 const editor = vscode.window.activeTextEditor;
954 if (editor === undefined || document === undefined) {
955 logger.error(getMessage("noFocusedEditors"));
956 logger.Gui.error(getMessage("openFileToApplyHeader"));
957 return;
958 }
959 this.updateFileInfo(editor, document);
960 // Checking that the meta data is filled out.
961 if (
962 this.documentBody === undefined || this.filePath === undefined
963 || this.fileName === undefined || this.fileExtension === undefined
964 || this.languageId === undefined || this.documentEOL === undefined
965 || this.documentVersion === undefined
966 ) {
967 logger.error(getMessage("corruptedFileMetaData"));
968 logger.Gui.error(getMessage("errorDuringFunctionCall", "injectHeader"));
969 return;
970 }
971 // Check that the file is not in the exclusion list.
972 if (!await this.allowedToActivate()) {
973 logger.info(getMessage("fileExcludedActivationDisabled"));
974 return;
975 }
976 // Making sure that the target document is still open.
977 if (this.documentBody.isClosed) {
978 logger.warning(getMessage("closedDocument"));
979 logger.Gui.warning(getMessage("updateAbortedBecauseFileClosedSyncCancelled"));
980 return;
981 }
982 // Some logging
983 const msg = getMessage("inputArgs", JSON.stringify(this.documentBody), JSON.stringify(this.filePath), JSON.stringify(this.fileName), JSON.stringify(this.fileExtension), JSON.stringify(this.languageId), JSON.stringify(this.documentEOL), JSON.stringify(this.documentVersion));
984 logger.Gui.debug(msg);
985 logger.debug(msg);
986 // Determining the correct comment prefix
987 const determineComment: CommentStyle = await this.determineCorrectComment();
988 const comments: string[] = await this.getCorrectCommentPrefix(determineComment);
989 // attempt to locate the header
990 const response: boolean | undefined = this.locateIfHeaderPresent(comments);
991 if (response === undefined) {
992 logger.Gui.warning(getMessage("updateAbortedBecauseFileClosedSyncCancelled"));
993 return;
994 }
995 if (response === false) {
997 logger.Gui.info(getMessage("headerNotFound"));
998 return;
999 }
1000 logger.Gui.warning(getMessage("headerNotFound"));
1001 const questionResponse: boolean = await query.confirm(getMessage("headerInjectQuestion"));
1002 if (questionResponse === false) {
1003 logger.Gui.info(getMessage("headerInjectQuestionRefused"));
1004 return;
1005 }
1006 const status: number = await this.writeHeaderToFile(editor, comments);
1007 if (status === this.Config.get("statusError")) {
1008 logger.Gui.error(getMessage("headerWriteFailed"));
1009 return;
1010 }
1011 logger.Gui.info(getMessage("headerWriteSuccess"));
1012 }
1013 if (response === true) {
1014 logger.Gui.info(getMessage("updatingEditionDate"));
1015 await this.updateEditDate(editor, comments);
1016 return;
1017 }
1018 }
1019}
Intelligent file header generation and management system.
locateIfHeaderPresent(comments:string[])
Scans document to detect existing header presence and boundaries.
constructor(languageComment:LazyFileLoader|undefined=undefined, editor:vscode.TextEditor|undefined=undefined, randomLogoInstance:RandomLogo|undefined=undefined)
Constructor for CommentGenerator class.
Generic lazy file loader with caching and type safety @template T The expected type of the loaded fil...
import *as vscode from vscode
export const promptToCreateIfMissing
Whether to prompt user to create header if missing during operations.
Definition constants.ts:232
export const randomLogo
Whether to use random logo selection instead of default logo.
Definition constants.ts:235
export const refreshOnSave
Whether to automatically refresh headers when files are saved.
Definition constants.ts:229
Defines comment style configuration for different programming languages.
Structure representing a loaded ASCII art logo with metadata.
export const logger
Singleton logger instance providing unified logging interface for the entire extension.
Definition logger.ts:910
export const getMessage
Exported function for direct message retrieval.
export const Record< string,(...args:any[])=> string
export type CodeConfigType
Type alias for the Configuration class.
export const CodeConfig
Exported configuration singleton for extension-wide access @export Primary configuration interface us...
export const query
Convenience singleton export for direct access to Query functionality @export Primary interface for u...
Definition querier.ts:345