Skip to content

Commit

Permalink
1.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
nareyko committed Dec 19, 2023
1 parent addadf2 commit b5f1137
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 142 deletions.
55 changes: 54 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,59 @@
# Changelog

## [1.0.2] - 2022-XX-XX
## [1.0.3] - 2022-12-19

### Changed

- Simplified the configuration retrieval in `src/config.ts` and refactored the `createDiagnostics` function in `src/diagnostics.ts` to improve readability and maintainability. The `createDiagnostics` function now also takes into account the `showErrors` configuration setting when creating diagnostic messages from errors.
- Simplified `extension.ts` by moving the `handlePythonDocument` function to `workspace.ts` and using the `processWorkspaces` function for linting and handling of configuration change events. The handling of document change and open events now uses the `handleDocumentEvent` function.
- Improved documentation and refactored `executeRadon` function in `src/radon.ts` to construct command arguments in a more structured way. Improved error handling in `executeRadon` and `processRadonOutput` functions. The `processRadonOutput` function now handles file paths in a more robust way.
- In `src/radonTypes.ts`, the `RadonBlock` and `RadonOutput` definitions have been changed from interfaces to types, allowing them to be used in more flexible ways, such as in union types or mapped types. Added semicolons at the end of these type definitions.
- Refactored the `processPythonFiles` and `processAllWorkspaceFolders` functions to use the `Array.filter` and `Array.forEach` methods instead of a for loop. The `processAllWorkspaceFolders` function now also returns a Promise that resolves to void.

### Removed

- From `extension.ts`:

- Removed the inline definition of `handlePythonDocument` function.
- Removed `reloadConfig` import as it's no longer used.

- Replaced direct calls to `processAllWorkspaceFolders` and `handlePythonDocument` with a new queue-based approach.

- In `processRadonOutput` function:

- Removed unnecessary array check. The function now assumes that the `filePaths` variable is always an array.

- Cleaned up `processWorkspace`, `processFile`, `processPythonFiles`, and `processAllWorkspaceFolders` functions:

### Added

- Introduced a new configuration option "vscodeRadonLinter.showErrors" in `package.json`. This option, when set to true, will display errors identified by the Radon tool.
- Added "\*.pyx" and "cpython" to the default glob patterns for files and folders to exclude in `package.json`.

- Added new imports to `extension.ts`:

- `handlePythonDocument` from `workspace.ts`
- `PromiseQueue`

- Introduced a new PromiseQueue to handle tasks in a queue.

- Added new functions:

- `processWorkspaces` to process all workspace folders and add them to the queue.
- `handleDocumentEvent` to handle document events and add them to the queue.
- `handlePythonDocument` to handle Python documents. This function takes a document, a diagnostic collection, and an action performed on the document as parameters. It checks if the document is a Python file and if so, it processes the file for linting.

- Added detailed comments to the following functions explaining their purpose, parameters, and return value:

- `processRadonOutput`
- `processWorkspace`
- `processFile`
- `processPythonFiles`
- `processAllWorkspaceFolders`

- Enhanced logging in `processRadon` function. The function now logs the target path if the "debug" configuration option is set to true.

## [1.0.2] - 2022-12-19

### Changed

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-radon-linter",
"displayName": "vscode-radon-linter",
"description": "This Visual Studio Code extension provides Python linting functionality using the Radon library. Once installed, the extension automatically checks Python files for potential issues and displays them in the Problems tab. This helps developers identify and fix issues such as code complexity, maintainability, and other potential problems that could lead to bugs or make the code harder to read and maintain. The extension is easy to use and integrates seamlessly with Visual Studio Code, making it a valuable tool for Python developers who want to ensure their code is clean, efficient, and follows best practices.",
"version": "1.0.2",
"version": "1.0.3",
"icon": "vscode-radon-linter128x128.png",
"keywords": [
"python",
Expand Down Expand Up @@ -77,7 +77,9 @@
"items": {
"type": "string"
},
"default": [],
"default": [
"*.pyx"
],
"description": "Glob patterns for files to exclude."
},
"vscodeRadonLinter.ignoreFolders": {
Expand All @@ -86,14 +88,19 @@
"type": "string"
},
"default": [
"node_modules,venv,.venv,env,.env"
"node_modules,venv,.venv,env,.env,cpython"
],
"description": "Glob patterns for folders to ignore."
},
"vscodeRadonLinter.showRadonPathWarning": {
"type": "boolean",
"default": true,
"description": "Show a warning message to recheck the path to the radon executable."
},
"vscodeRadonLinter.showErrors": {
"type": "boolean",
"default": true,
"description": "Display errors identified by the Radon tool."
}
}
}
Expand Down
17 changes: 5 additions & 12 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,10 @@
*/
import * as vscode from "vscode";

// Get the initial configuration for the vscodeRadonLinter extension
let config = vscode.workspace.getConfiguration("vscodeRadonLinter");

// Function to get the current configuration
// Define a function to get the current configuration
export function getConfig() {
// Return the current configuration
return config;
}

// Function to reload the configuration
export function reloadConfig() {
// Update the configuration by getting the latest from the workspace
config = vscode.workspace.getConfiguration("vscodeRadonLinter");
// Use the getConfiguration method from the vscode.workspace module
// to get the configuration for the extension with the ID "vscodeRadonLinter"
// The getConfiguration method returns an object with the current configuration settings
return vscode.workspace.getConfiguration("vscodeRadonLinter");
}
109 changes: 79 additions & 30 deletions src/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,92 @@ import * as vscode from "vscode";
import { getConfig } from "./config";
import { RadonBlock } from "./radonTypes";

// Function to create diagnostics from Radon output
export function createDiagnostics(radonOutput: RadonBlock[]): vscode.Diagnostic[] {
// Initialize an empty array of diagnostics
let diagnostics: vscode.Diagnostic[] = [];
/**
* Creates a diagnostic message from a RadonBlock object if its complexity is greater than or equal to the minimum complexity.
* @param block - The RadonBlock object to create a diagnostic from.
* @param minComplexity - The minimum complexity for a block to be considered complex.
* @returns A vscode.Diagnostic object if the block's complexity is greater than or equal to the minimum complexity, or null otherwise.
*/
function createDiagnosticFromBlock(block: RadonBlock, minComplexity: number): vscode.Diagnostic | null {
// If the block's complexity is greater than or equal to the minimum complexity...
if (block.complexity >= minComplexity) {
// Create a range object representing the line of code where the block is located.
const range = new vscode.Range(block.lineno - 1, 0, block.lineno - 1, Number.MAX_VALUE);

if (Array.isArray(radonOutput)) {
// Get the minimum complexity from the configuration, or use 0 as a default
const minComplexity = getConfig().get<number>("minComplexity") || 0;
// For each block in the Radon output
radonOutput.forEach((block: RadonBlock) => {
// If the complexity of the block is greater than or equal to the minimum complexity
if (block.complexity >= minComplexity) {
// Create a range for the diagnostic, which is the line where the block starts
const range = new vscode.Range(block.lineno - 1, 0, block.lineno - 1, Number.MAX_VALUE);

// Create a message for the diagnostic, which includes the type, name, and complexity of the block
const message = `Radon: ${block.type} '${block.name}' has a complexity of ${block.complexity}`;

// Determine the severity of the diagnostic based on the complexity of the block
const severity =
block.complexity > 5 ? vscode.DiagnosticSeverity.Warning : vscode.DiagnosticSeverity.Information;

// Add the diagnostic to the array of diagnostics
diagnostics.push(new vscode.Diagnostic(range, message, severity));
}
});
} else if (typeof radonOutput === "object" && radonOutput !== null && "error" in radonOutput) {
// Create a message string describing the block's type, name, and complexity.
const message = `Radon: ${block.type} '${block.name}' has a complexity of ${block.complexity}`;

// Determine the severity of the diagnostic based on the block's complexity.
const severity = block.complexity > 5 ? vscode.DiagnosticSeverity.Warning : vscode.DiagnosticSeverity.Information;

// Return a new vscode.Diagnostic object with the range, message, and severity.
return new vscode.Diagnostic(range, message, severity);
}

// If the block's complexity is less than the minimum complexity, return null.
return null;
}

/**
* Creates a diagnostic message from an error in the radon output.
* @param radonOutput - The output from the radon tool.
* @param showErrors - A flag indicating whether to show errors.
* @returns A vscode.Diagnostic object if an error is present in the radon output and showErrors is true, or null otherwise.
*/
function createDiagnosticFromError(radonOutput: any, showErrors: boolean): vscode.Diagnostic | null {
// If radonOutput is an object, is not null, contains an "error" property, and showErrors is true...
if (typeof radonOutput === "object" && radonOutput !== null && "error" in radonOutput && showErrors) {
// Initialize the line number to 0.
let line = 0;

// Try to match the error message with a regular expression to extract the line number.
const errorLineMatch = (radonOutput["error"] as string).match(/line (\d+)/);

// If a match was found, parse the line number from the match and subtract 1 (because line numbers in vscode start from 0).
if (errorLineMatch) {
line = parseInt(errorLineMatch[1]) - 1; // -1 because lines are 0-indexed in vscode
line = parseInt(errorLineMatch[1]) - 1;
}

// Create a range object representing the line of code where the error occurred.
const range = new vscode.Range(line, 0, line, Number.MAX_VALUE);

// Create a message string containing the error message from the radon output.
const message = `Radon error: ${radonOutput["error"]}`;

// Set the severity of the diagnostic to Error.
const severity = vscode.DiagnosticSeverity.Error;
diagnostics.push(new vscode.Diagnostic(range, message, severity));

// Return a new vscode.Diagnostic object with the range, message, and severity.
return new vscode.Diagnostic(range, message, severity);
}

// If radonOutput does not contain an error or showErrors is false, return null.
return null;
}

/**
* Creates an array of diagnostic messages from the output of the radon tool.
* @param radonOutput - The output from the radon tool, which can be an array of RadonBlock objects or an error object.
* @returns An array of vscode.Diagnostic objects representing the complex blocks or the error in the radon output.
*/
export function createDiagnostics(radonOutput: RadonBlock[] | any): vscode.Diagnostic[] {
// Get the showErrors and minComplexity settings from the configuration.
const showErrors = getConfig().get<boolean>("showErrors") ?? true;
const minComplexity = getConfig().get<number>("minComplexity") || 0;

// If radonOutput is an array (i.e., it's an array of RadonBlock objects)...
if (Array.isArray(radonOutput)) {
// Map each RadonBlock object to a diagnostic message (if its complexity is greater than or equal to minComplexity),
// filter out any null values (i.e., blocks whose complexity is less than minComplexity),
// and return the resulting array of diagnostic messages.
return radonOutput
.map((block) => createDiagnosticFromBlock(block, minComplexity))
.filter(Boolean) as vscode.Diagnostic[];
} else {
// If radonOutput is not an array (i.e., it's an error object)...
// Create a diagnostic message from the error (if showErrors is true) and return an array containing the diagnostic message.
// If showErrors is false or there's no error in radonOutput, return an empty array.
const errorDiagnostic = createDiagnosticFromError(radonOutput, showErrors);
return errorDiagnostic ? [errorDiagnostic] : [];
}
// Return the array of diagnostics
return diagnostics;
}
59 changes: 19 additions & 40 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,9 @@
* Licensed under the MIT License. See LICENSE.txt in the project root for license information.
*/
import * as vscode from "vscode";
import { getConfig, reloadConfig } from "./config";
import { processFile, processAllWorkspaceFolders } from "./workspace";

// Function to handle Python documents
function handlePythonDocument(
document: vscode.TextDocument, // The document to handle
diagnosticCollection: vscode.DiagnosticCollection, // The collection of diagnostics
action: string // The action performed on the document
) {
// If the document is not a Python file, return
if (document.languageId !== "python") {
return;
}

// If debug mode is on, log the linting action
if (getConfig().get<boolean>("debug")) {
console.log(`Linting ${action} file: ${document.uri}`);
}

// Process the file for linting
processFile(document.uri, diagnosticCollection);
}
import { getConfig } from "./config";
import { processAllWorkspaceFolders, handlePythonDocument } from "./workspace";
import { PromiseQueue } from "./promisequeue";

// Function to activate the extension
export function activate(context: vscode.ExtensionContext) {
Expand All @@ -39,43 +20,41 @@ export function activate(context: vscode.ExtensionContext) {
// Add the diagnostic collection to the context's subscriptions
context.subscriptions.push(diagnosticCollection);

// Create a new PromiseQueue
const queue = new PromiseQueue();
// Function to process all workspace folders and add to queue
const processWorkspaces = () => queue.enqueue(() => processAllWorkspaceFolders(diagnosticCollection));

// Process all workspace folders for linting
processWorkspaces();

// Register a command for linting
const disposable = vscode.commands.registerCommand("extension.vscodeRadonLinter.lint", () => {
// Process all workspace folders for linting
processAllWorkspaceFolders(diagnosticCollection);
});
const disposable = vscode.commands.registerCommand("extension.vscodeRadonLinter.lint", processWorkspaces);

// Add the command to the context's subscriptions
context.subscriptions.push(disposable);

// Handle document change events
vscode.workspace.onDidChangeTextDocument((event) => {
// Handle the changed document
handlePythonDocument(event.document, diagnosticCollection, "changed");
});
// Function to handle document events and add to queue
const handleDocumentEvent = (document: vscode.TextDocument, eventType: string) =>
queue.enqueue(() => handlePythonDocument(document, diagnosticCollection, eventType));

vscode.workspace.onDidChangeTextDocument((event) => handleDocumentEvent(event.document, "changed"));

// Handle document open events
vscode.workspace.onDidOpenTextDocument((document) => {
// Handle the opened document
handlePythonDocument(document, diagnosticCollection, "opened");
});
vscode.workspace.onDidOpenTextDocument((document) => handleDocumentEvent(document, "opened"));

// Handle configuration change events
vscode.workspace.onDidChangeConfiguration((event) => {
// If the configuration change affects the linter
if (event.affectsConfiguration("vscodeRadonLinter")) {
// Reload the configuration
reloadConfig();
// If debug mode is on, log the configuration change
if (getConfig().get<boolean>("debug")) {
console.log("Configuration changed, reloading...");
}
// Re-process all workspace folders with the new configuration
processAllWorkspaceFolders(diagnosticCollection);
processWorkspaces();
}
});
// Process all workspace folders for linting
processAllWorkspaceFolders(diagnosticCollection);

// Check if the warning message should be shown
if (getConfig().get("showRadonPathWarning")) {
Expand Down
Loading

0 comments on commit b5f1137

Please sign in to comment.