[reword]
This commit is contained in:
@@ -4,9 +4,9 @@ import { bfVisitor } from './generated/bfVisitor';
|
|||||||
import { DiagnosticSeverity } from 'vscode-languageclient';
|
import { DiagnosticSeverity } from 'vscode-languageclient';
|
||||||
import { getTree } from './BranFlakesParseRunner';
|
import { getTree } from './BranFlakesParseRunner';
|
||||||
import { RuleNode } from 'antlr4ts/tree/RuleNode';
|
import { RuleNode } from 'antlr4ts/tree/RuleNode';
|
||||||
import InputStrategy from './input/InputStrategy';
|
import type InputStrategy from './input/InputStrategy';
|
||||||
|
|
||||||
export default class BranFlakesExecutorVisitor
|
export class BranFlakesExecutorVisitor
|
||||||
extends AbstractParseTreeVisitor<Promise<void>>
|
extends AbstractParseTreeVisitor<Promise<void>>
|
||||||
implements bfVisitor<Promise<void>>
|
implements bfVisitor<Promise<void>>
|
||||||
{
|
{
|
||||||
|
4
client/src/command/BranFlakesCommand.ts
Normal file
4
client/src/command/BranFlakesCommand.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export interface BranFlakesCommand {
|
||||||
|
getCommandName(): string;
|
||||||
|
getCommandHandler(): (...args: any) => Promise<any>;
|
||||||
|
}
|
@@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
export interface Command{
|
|
||||||
getCommandName():string;
|
|
||||||
getCommandHandler():(...args:any)=>Promise<any>;
|
|
||||||
}
|
|
@@ -1,7 +1,6 @@
|
|||||||
import { window } from 'vscode';
|
import { window } from 'vscode';
|
||||||
import { Command as BranFlakesCommand } from './Command';
|
import type { BranFlakesCommand } from './BranFlakesCommand';
|
||||||
import { VSCodePromptInputStrategy } from '../input/VSCodePromptInputStrategy';
|
import { VSCodePromptInputStrategy } from '../input/VSCodePromptInputStrategy';
|
||||||
import BranFlakesExecutorVisitor from '../BranFlakesExecutorVisitor';
|
|
||||||
|
|
||||||
export class CompileBranFlakesCommand implements BranFlakesCommand {
|
export class CompileBranFlakesCommand implements BranFlakesCommand {
|
||||||
getCommandName() {
|
getCommandName() {
|
||||||
@@ -14,6 +13,10 @@ export class CompileBranFlakesCommand implements BranFlakesCommand {
|
|||||||
const inputStrategy = new VSCodePromptInputStrategy(
|
const inputStrategy = new VSCodePromptInputStrategy(
|
||||||
window.showInputBox
|
window.showInputBox
|
||||||
);
|
);
|
||||||
|
const { BranFlakesExecutorVisitor } = await import(
|
||||||
|
'../BranFlakesExecutorVisitor'
|
||||||
|
);
|
||||||
|
|
||||||
const output = await BranFlakesExecutorVisitor.run(
|
const output = await BranFlakesExecutorVisitor.run(
|
||||||
text,
|
text,
|
||||||
fn,
|
fn,
|
@@ -4,14 +4,15 @@
|
|||||||
* ------------------------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------------------------ */
|
||||||
|
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { ExtensionContext, commands, window } from 'vscode';
|
import { commands } from 'vscode';
|
||||||
|
import type { ExtensionContext } from 'vscode';
|
||||||
import {
|
import {
|
||||||
LanguageClient,
|
LanguageClient,
|
||||||
LanguageClientOptions,
|
LanguageClientOptions,
|
||||||
ServerOptions,
|
ServerOptions,
|
||||||
TransportKind,
|
TransportKind,
|
||||||
} from 'vscode-languageclient';
|
} from 'vscode-languageclient';
|
||||||
import { CompileBranFlakesCommand } from './command/CompileCommand';
|
import { CompileBranFlakesCommand } from './command/CompileBranFlakesCommand';
|
||||||
|
|
||||||
let client: LanguageClient;
|
let client: LanguageClient;
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { CancellationToken, InputBoxOptions } from 'vscode';
|
import type { CancellationToken, InputBoxOptions } from 'vscode';
|
||||||
import InputStrategy from './InputStrategy';
|
import type InputStrategy from './InputStrategy';
|
||||||
|
|
||||||
export class VSCodePromptInputStrategy implements InputStrategy {
|
export class VSCodePromptInputStrategy implements InputStrategy {
|
||||||
private inputQueue: string = '';
|
private inputQueue: string = '';
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
"author": "Atreya Bain",
|
"author": "Atreya Bain",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"publisher": "atreyabain",
|
"publisher": "atreyabain",
|
||||||
"version": "0.2.0",
|
"version": "0.2.1",
|
||||||
"icon": "assets/128.png",
|
"icon": "assets/128.png",
|
||||||
"categories": [],
|
"categories": ["Programming Languages","Linters"],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"multi-root ready",
|
"multi-root ready",
|
||||||
"brainfuck",
|
"brainfuck",
|
||||||
|
@@ -3,31 +3,26 @@
|
|||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
* ------------------------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------------------------ */
|
||||||
import {
|
import {
|
||||||
createConnection,
|
createConnection,
|
||||||
TextDocuments,
|
TextDocuments,
|
||||||
Diagnostic,
|
Diagnostic,
|
||||||
DiagnosticSeverity,
|
DiagnosticSeverity,
|
||||||
ProposedFeatures,
|
ProposedFeatures,
|
||||||
InitializeParams,
|
InitializeParams,
|
||||||
DidChangeConfigurationNotification,
|
DidChangeConfigurationNotification,
|
||||||
CompletionItem,
|
CompletionItem,
|
||||||
CompletionItemKind,
|
CompletionItemKind,
|
||||||
TextDocumentPositionParams,
|
TextDocumentPositionParams,
|
||||||
TextDocumentSyncKind,
|
TextDocumentSyncKind,
|
||||||
InitializeResult,
|
InitializeResult,
|
||||||
Position,
|
|
||||||
} from 'vscode-languageserver';
|
} from 'vscode-languageserver';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { TextDocument } from 'vscode-languageserver-textdocument';
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
||||||
|
|
||||||
|
|
||||||
// Create a connection for the server. The connection uses Node's IPC as a transport.
|
// Create a connection for the server. The connection uses Node's IPC as a transport.
|
||||||
// Also include all preview / proposed LSP features.
|
// Also include all preview / proposed LSP features.
|
||||||
let connection = createConnection(ProposedFeatures.all);
|
let connection = createConnection(ProposedFeatures.all);
|
||||||
|
|
||||||
|
|
||||||
// Create a simple text document manager. The text document manager
|
// Create a simple text document manager. The text document manager
|
||||||
// supports full document sync only
|
// supports full document sync only
|
||||||
let documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
|
let documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
|
||||||
@@ -37,60 +32,60 @@ let hasWorkspaceFolderCapability: boolean = false;
|
|||||||
let hasDiagnosticRelatedInformationCapability: boolean = false;
|
let hasDiagnosticRelatedInformationCapability: boolean = false;
|
||||||
|
|
||||||
connection.onInitialize((params: InitializeParams) => {
|
connection.onInitialize((params: InitializeParams) => {
|
||||||
let capabilities = params.capabilities;
|
let capabilities = params.capabilities;
|
||||||
|
|
||||||
// Does the client support the `workspace/configuration` request?
|
// Does the client support the `workspace/configuration` request?
|
||||||
// If not, we will fall back using global settings
|
// If not, we will fall back using global settings
|
||||||
hasConfigurationCapability = !!(
|
hasConfigurationCapability = !!(
|
||||||
capabilities.workspace && !!capabilities.workspace.configuration
|
capabilities.workspace && !!capabilities.workspace.configuration
|
||||||
);
|
);
|
||||||
hasWorkspaceFolderCapability = !!(
|
hasWorkspaceFolderCapability = !!(
|
||||||
capabilities.workspace && !!capabilities.workspace.workspaceFolders
|
capabilities.workspace && !!capabilities.workspace.workspaceFolders
|
||||||
);
|
);
|
||||||
hasDiagnosticRelatedInformationCapability = !!(
|
hasDiagnosticRelatedInformationCapability = !!(
|
||||||
capabilities.textDocument &&
|
capabilities.textDocument &&
|
||||||
capabilities.textDocument.publishDiagnostics &&
|
capabilities.textDocument.publishDiagnostics &&
|
||||||
capabilities.textDocument.publishDiagnostics.relatedInformation
|
capabilities.textDocument.publishDiagnostics.relatedInformation
|
||||||
);
|
);
|
||||||
|
|
||||||
const result: InitializeResult = {
|
const result: InitializeResult = {
|
||||||
capabilities: {
|
capabilities: {
|
||||||
textDocumentSync: TextDocumentSyncKind.Incremental,
|
textDocumentSync: TextDocumentSyncKind.Incremental,
|
||||||
// Tell the client that the server supports code completion
|
// Tell the client that the server supports code completion
|
||||||
completionProvider: {
|
completionProvider: {
|
||||||
resolveProvider: false,
|
resolveProvider: false,
|
||||||
triggerCharacters: ['.'],
|
triggerCharacters: ['.'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (hasWorkspaceFolderCapability) {
|
if (hasWorkspaceFolderCapability) {
|
||||||
result.capabilities.workspace = {
|
result.capabilities.workspace = {
|
||||||
workspaceFolders: {
|
workspaceFolders: {
|
||||||
supported: true,
|
supported: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.onInitialized(() => {
|
connection.onInitialized(() => {
|
||||||
if (hasConfigurationCapability) {
|
if (hasConfigurationCapability) {
|
||||||
// Register for all configuration changes.
|
// Register for all configuration changes.
|
||||||
connection.client.register(
|
connection.client.register(
|
||||||
DidChangeConfigurationNotification.type,
|
DidChangeConfigurationNotification.type,
|
||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (hasWorkspaceFolderCapability) {
|
if (hasWorkspaceFolderCapability) {
|
||||||
connection.workspace.onDidChangeWorkspaceFolders(_event => {
|
connection.workspace.onDidChangeWorkspaceFolders(_event => {
|
||||||
connection.console.log('Workspace folder change event received.');
|
connection.console.log('Workspace folder change event received.');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// The example settings
|
// The example settings
|
||||||
interface ExampleSettings {
|
interface ExampleSettings {
|
||||||
maxNumberOfProblems: number;
|
maxNumberOfProblems: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The global settings, used when the `workspace/configuration` request is not supported by the client.
|
// The global settings, used when the `workspace/configuration` request is not supported by the client.
|
||||||
@@ -103,154 +98,142 @@ let globalSettings: ExampleSettings = defaultSettings;
|
|||||||
let documentSettings: Map<string, Thenable<ExampleSettings>> = new Map();
|
let documentSettings: Map<string, Thenable<ExampleSettings>> = new Map();
|
||||||
|
|
||||||
connection.onDidChangeConfiguration(change => {
|
connection.onDidChangeConfiguration(change => {
|
||||||
if (hasConfigurationCapability) {
|
if (hasConfigurationCapability) {
|
||||||
// Reset all cached document settings
|
// Reset all cached document settings
|
||||||
documentSettings.clear();
|
documentSettings.clear();
|
||||||
} else {
|
} else {
|
||||||
globalSettings = <ExampleSettings>(
|
globalSettings = <ExampleSettings>(
|
||||||
(change.settings.languageServerExample || defaultSettings)
|
(change.settings.languageServerExample || defaultSettings)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Revalidate all open text documents
|
// Revalidate all open text documents
|
||||||
documents.all().forEach(validateTextDocument);
|
Promise.all(documents.all().map(validateTextDocument)).catch(e => {
|
||||||
|
connection.console.log('Failed to validate text documents');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getDocumentSettings(resource: string): Thenable<ExampleSettings> {
|
function getDocumentSettings(resource: string): Thenable<ExampleSettings> {
|
||||||
if (!hasConfigurationCapability) {
|
if (!hasConfigurationCapability) {
|
||||||
return Promise.resolve(globalSettings);
|
return Promise.resolve(globalSettings);
|
||||||
}
|
}
|
||||||
let result = documentSettings.get(resource);
|
let result = documentSettings.get(resource);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
result = connection.workspace.getConfiguration({
|
result = connection.workspace.getConfiguration({
|
||||||
scopeUri: resource,
|
scopeUri: resource,
|
||||||
section: 'languageServerExample',
|
section: 'languageServerExample',
|
||||||
});
|
});
|
||||||
documentSettings.set(resource, result);
|
documentSettings.set(resource, result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only keep settings for open documents
|
// Only keep settings for open documents
|
||||||
documents.onDidClose(e => {
|
documents.onDidClose(e => {
|
||||||
documentSettings.delete(e.document.uri);
|
documentSettings.delete(e.document.uri);
|
||||||
});
|
});
|
||||||
|
|
||||||
// The content of a text document has changed. This event is emitted
|
// The content of a text document has changed. This event is emitted
|
||||||
// when the text document first opened or when its content has changed.
|
// when the text document first opened or when its content has changed.
|
||||||
documents.onDidChangeContent(change => {
|
documents.onDidChangeContent(change => {
|
||||||
//change.contentChanges;
|
validateTextDocument(change.document);
|
||||||
validateTextDocument(change.document);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//Run when saved
|
//Run when saved
|
||||||
documents.onDidSave(change => {
|
documents.onDidSave(change => {
|
||||||
validateTextDocument(change.document);
|
validateTextDocument(change.document);
|
||||||
});
|
});
|
||||||
|
|
||||||
const validateBrackets = (text: string) => {
|
const validateBrackets = (text: string) => {
|
||||||
let count = 0, lp: number[] = [],issues:number[]=[];
|
let count = 0,
|
||||||
const textsplit = text.split('');
|
lp: number[] = [],
|
||||||
textsplit.forEach((x, i) => {
|
issues: number[] = [];
|
||||||
if (x === '[' || x === ']') {
|
const textsplit = text.split('');
|
||||||
|
textsplit.forEach((x, i) => {
|
||||||
|
if (x === '[' || x === ']') {
|
||||||
|
if (x === '[') {
|
||||||
|
lp.push(i);
|
||||||
|
}
|
||||||
|
if (x === ']') {
|
||||||
|
if (lp.length === 0) {
|
||||||
|
issues.push(i);
|
||||||
|
}
|
||||||
|
lp.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (x === '[') {lp.push(i);}
|
return [...lp, ...issues];
|
||||||
if (x === ']') {if(lp.length===0) {issues.push(i);}lp.pop();}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return [...lp,...issues];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async function validateTextDocument(textDocument: TextDocument): Promise<void> {
|
async function validateTextDocument(textDocument: TextDocument): Promise<void> {
|
||||||
// In this simple example we get the settings for every validate run.
|
// In this simple example we get the settings for every validate run.
|
||||||
let settings = await getDocumentSettings(textDocument.uri);
|
let settings = await getDocumentSettings(textDocument.uri);
|
||||||
// The validator creates diagnostics for all uppercase words length 2 and more
|
// The validator creates diagnostics for all uppercase words length 2 and more
|
||||||
const text = textDocument.getText();
|
const text = textDocument.getText();
|
||||||
|
|
||||||
let problems = 0;
|
let problems = 0;
|
||||||
let diagnostics: Diagnostic[] = [];
|
let diagnostics: Diagnostic[] = [];
|
||||||
const issues = validateBrackets(text);
|
const issues = validateBrackets(text);
|
||||||
|
|
||||||
diagnostics.push(...issues.map<Diagnostic>(e => ({
|
diagnostics.push(
|
||||||
message: 'Brackets unmatched',
|
...issues.map<Diagnostic>(e => ({
|
||||||
range:{
|
message: 'Brackets unmatched',
|
||||||
start: textDocument.positionAt(e),
|
range: {
|
||||||
end: textDocument.positionAt(e+1),
|
start: textDocument.positionAt(e),
|
||||||
},
|
end: textDocument.positionAt(e + 1),
|
||||||
severity:DiagnosticSeverity.Error,
|
},
|
||||||
code:'[ and ]',
|
severity: DiagnosticSeverity.Error,
|
||||||
})));
|
code: '[ and ]',
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
// diagnostics.push({
|
// Send the computed diagnostics to VSCode.
|
||||||
// message: 'Brackets not matched',
|
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
||||||
// range: {
|
|
||||||
// start: { line: 0, character: 0 },
|
|
||||||
// end: { line: 0, character: 0 },
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// diagnostics.push(<Diagnostic>{
|
|
||||||
// severity: DiagnosticSeverity.Information,
|
|
||||||
// range: {
|
|
||||||
// start: textDocument.positionAt(0),
|
|
||||||
// end: textDocument.positionAt(1),
|
|
||||||
// },
|
|
||||||
// // message:`HI:(${text})(${result.hasErrors()},${result.hasWarnings()})`,
|
|
||||||
// message: `Parsing Failed`,
|
|
||||||
// source: 'test',
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Send the computed diagnostics to VSCode.
|
|
||||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This handler provides the initial list of the completion items.
|
// This handler provides the initial list of the completion items.
|
||||||
connection.onCompletion(
|
connection.onCompletion(
|
||||||
(_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {
|
(_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {
|
||||||
const completions: CompletionItem[] = [
|
const completions: CompletionItem[] = [
|
||||||
{
|
{
|
||||||
label: '+',
|
label: '+',
|
||||||
detail: 'Addition',
|
detail: 'Addition',
|
||||||
documentation: 'Add one to cell',
|
documentation: 'Add one to cell',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '-',
|
label: '-',
|
||||||
detail: 'Subtraction',
|
detail: 'Subtraction',
|
||||||
documentation: 'Subtract one from cell',
|
documentation: 'Subtract one from cell',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: ',',
|
label: ',',
|
||||||
detail: 'Input',
|
detail: 'Input',
|
||||||
documentation: 'Ask for input (Stored in the ASCII format)',
|
documentation: 'Ask for input (Stored in the ASCII format)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '.',
|
label: '.',
|
||||||
detail: 'Output',
|
detail: 'Output',
|
||||||
documentation: 'Output the equivalent ASCII character',
|
documentation: 'Output the equivalent ASCII character',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '>',
|
label: '>',
|
||||||
detail: 'Right Shift',
|
detail: 'Right Shift',
|
||||||
documentation: 'Shift the pointer one cell to the right',
|
documentation: 'Shift the pointer one cell to the right',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '<',
|
label: '<',
|
||||||
detail: 'Left Shift',
|
detail: 'Left Shift',
|
||||||
documentation: 'Shift the pointer one cell to the Left',
|
documentation: 'Shift the pointer one cell to the Left',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return completions.map(e => {
|
return completions.map(e => {
|
||||||
e.kind = CompletionItemKind.Operator;
|
e.kind = CompletionItemKind.Operator;
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Make the text document manager listen on the connection
|
// Make the text document manager listen on the connection
|
||||||
// for open, change and close text document events
|
// for open, change and close text document events
|
||||||
documents.listen(connection);
|
documents.listen(connection);
|
||||||
|
Reference in New Issue
Block a user