Skip to content

Commit 9e1260b

Browse files
committed
a lot of bug fixes
1 parent 376f049 commit 9e1260b

File tree

13 files changed

+69
-41
lines changed

13 files changed

+69
-41
lines changed

server/src/ast.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Identifier, Literal, SourceLocation, Node, Position as EsPosition } from 'estree';
2-
import { AUTOCOMPLETE_TYPES, Chapter, Context, DeclarationKind, DECLARATIONS, DeclarationSymbol, Documentation, ImportedSymbol, NODES, ParameterSymbol } from "./types";
2+
import { AUTOCOMPLETE_TYPES, Chapter, Context, DeclarationKind, DECLARATIONS, DeclarationSymbol, Documentation, EXPRESSIONS, ImportedSymbol, NODES, ParameterSymbol } from "./types";
33
import { autocomplete_labels, builtin_constants, builtin_functions, esPosInSourceLoc, findLastRange, getImportedName, getNodeChildren, isBuiltinConst, isBuiltinFunction, mapDeclarationSymbolToDocumentSymbol, mapMetaToCompletionItemKind, module_autocomplete, moduleExists, rangeToSourceLoc, sourceLocEquals, sourceLocInSourceLoc, sourceLocToRange, vsPosInSourceLoc, vsPosToEsPos } from "./utils";
44
import { CompletionItem, Diagnostic, DiagnosticSeverity, DiagnosticTag, DocumentHighlight, DocumentSymbol, Hover, Position, Range, TextEdit, WorkspaceEdit } from "vscode-languageserver";
55
import { parse as acornParse, Options } from 'acorn';
6-
import { parse as looseParse} from 'acorn-loose';
6+
import { parse as looseParse } from 'acorn-loose';
77
import { rules, bannedNodes } from "./rules";
88

99
export const DEFAULT_ECMA_VERSION = 6;
@@ -54,7 +54,7 @@ export class AST {
5454
catch (e) {
5555
this.ast = looseParse(text, acornOptions) as Node
5656
}
57-
// console.debug(JSON.stringify(this.ast, null, 2));
57+
console.debug(JSON.stringify(this.ast, null, 2));
5858

5959
this.context = context;
6060
this.uri = uri;
@@ -164,7 +164,7 @@ export class AST {
164164
const variableDeclaration: DeclarationSymbol = {
165165
name: name,
166166
scope: parent.loc!,
167-
meta: child.kind === "var" || child.kind === "let" ? "let" : "const",
167+
meta: child.kind === "var" || child.kind === "let" ? "let" : declaration.init?.type === EXPRESSIONS.LAMBDA ? "func" : "const",
168168
declarationKind: child.kind === "var" || child.kind === "let" ? DeclarationKind.KIND_LET : DeclarationKind.KIND_CONST,
169169
range: sourceLocToRange(declaration.loc!),
170170
selectionRange: sourceLocToRange(declaration.id.loc!),
@@ -173,9 +173,9 @@ export class AST {
173173
this.addDeclaration(name, variableDeclaration);
174174

175175

176-
if (declaration.init && declaration.init.type == DECLARATIONS.LAMBDA) {
176+
if (declaration.init && declaration.init.type == EXPRESSIONS.LAMBDA) {
177177
const lambda = declaration.init;
178-
if (lambda.params.length !== 0) variableDeclaration.parameters = [];
178+
variableDeclaration.parameters = [];
179179

180180
lambda.params.forEach(param => {
181181
if (param.loc) {
@@ -252,9 +252,13 @@ export class AST {
252252
})
253253
}
254254
// Handle anonymous lambdas
255-
else if (child.type === DECLARATIONS.LAMBDA && parent.type !== DECLARATIONS.VARIABLE) {
255+
else if (child.type === EXPRESSIONS.LAMBDA && parent.type !== DECLARATIONS.VARIABLE) {
256256
child.params.forEach(param => {
257-
const name = (param as Identifier).name;
257+
let name = "";
258+
if (param.type === NODES.IDENTIFIER)
259+
name = param.name
260+
else if (param.type === NODES.REST && param.argument.type === NODES.IDENTIFIER)
261+
name = param.argument.name
258262
const param_declaration: DeclarationSymbol = {
259263
name: name,
260264
scope: child.body.loc!,
@@ -340,7 +344,7 @@ export class AST {
340344

341345
getNodeChildren(node, true).forEach(node => {
342346
if (
343-
scopeFound
347+
scopeFound
344348
// We want to ignore scopes where the variable was redeclared
345349
// This occurs when there is an inner scope in the scope of our declaration, and the child node belongs in that scope
346350
&& !this.declarations.get(identifier.name)?.some(x => !sourceLocEquals(x.scope, declaration.scope) && sourceLocInSourceLoc(x.scope, declaration.scope) && sourceLocInSourceLoc(node.loc!, x.scope))
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { AST } from "../ast";
2+
import { Context } from "../types";
3+
import { Rule } from "./rule";
4+
import { ArrowFunctionExpression, Node } from "estree"
5+
import { DiagnosticSeverity } from "vscode-languageserver";
6+
7+
export const arrowFunctionExpressionRule = new class extends Rule<ArrowFunctionExpression> {
8+
public process(child: ArrowFunctionExpression, parent: Node, context: Context, ast: AST): void {
9+
let hasRestElement = false;
10+
for (const param of child.params) {
11+
if (hasRestElement) {
12+
ast.addDiagnostic("No params allowed after rest element", DiagnosticSeverity.Error, { start: param.loc!.start, end: child.params[child.params.length - 1].loc!.end });
13+
break;
14+
}
15+
16+
hasRestElement = param.type === "RestElement";
17+
}
18+
}
19+
}();

server/src/rules/callExpression.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export const callExpressionRule = new class extends Rule<CallExpression> {
1717
const loc = callee.loc;
1818
let declaration = ast.findDeclarationByName(callee.name, loc)
1919
if (declaration !== undefined) {
20-
if (declaration.meta !== "func")
20+
// We cannot check for let because they can be reassigned. Constants assigned to lambdas will still be "func"
21+
if (declaration.meta === "const")
2122
ast.addDiagnostic(`'${callee.name}' is not a function`, DiagnosticSeverity.Error, loc);
2223
if (declaration.parameters !== undefined || declaration.declarationKind === DeclarationKind.KIND_IMPORT) {
2324
let hasRestElement = false;

server/src/rules/functionDeclaration.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,5 @@ export const functionDeclarationRule = new class extends Rule<FunctionDeclaratio
1919

2020
hasRestElement = param.type === "RestElement";
2121
}
22-
23-
const paramNames = new Set();
24-
for (const param of child.params) {
25-
if (param.type === NODES.IDENTIFIER || (param.type === NODES.REST && param.argument.type === NODES.IDENTIFIER)) {
26-
const name = param.type === NODES.IDENTIFIER ? param.name : (param.argument as Identifier).name;
27-
28-
if (paramNames.has(name))
29-
ast.addDiagnostic("No duplicate param names", DiagnosticSeverity.Error, param.loc!);
30-
else
31-
paramNames.add(name);
32-
}
33-
}
34-
3522
}
3623
}();

server/src/rules/identifier.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { Context } from "../types";
88

99
export const identifierRule = new class extends Rule<Identifier> {
1010
public process(child: Identifier, parent: Node, context: Context, ast: AST): void {
11-
if (child.name === "eval")
12-
ast.addDiagnostic("eval is not allowed", DiagnosticSeverity.Error, child.loc!);
1311
if (parent.type !== DECLARATIONS.IMPORT) {
1412
// Ensure that all declarations have been processed
1513
ast.addDiagnosticCallback((node: Node) => {

server/src/rules/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { DECLARATIONS, EXPRESSIONS, NODES, STATEMENTS } from '../types';
33
import { Rule } from './rule';
44
import { binaryExpressionRule } from './binaryExpression';
55
import { conditonalExpressionRule } from './conditionalExpression';
6-
import { literalRule } from './literalExpression';
6+
import { literalRule } from './literal';
77
import { variableDeclarationRule } from './variableDeclaration';
88
import { assignmentExpressionRule } from './assignmentExpression';
99
import { functionDeclarationRule } from './functionDeclaration';
@@ -21,6 +21,7 @@ import { returnStatementRule } from './returnStatement';
2121
import { spreadElementRule } from './spreadElement';
2222
import { templateLiteralRule } from './templateLiteral';
2323
import { unaryExpressionRule } from './unaryExpression';
24+
import { arrowFunctionExpressionRule } from './arrowFunctionExpression';
2425

2526
export const rules: Map<string, Rule<Node>> = new Map();
2627
export const bannedNodes = new Set([
@@ -43,6 +44,7 @@ rules.set(EXPRESSIONS.ASSIGNMENT, assignmentExpressionRule);
4344
rules.set(EXPRESSIONS.CALL, callExpressionRule);
4445
rules.set(EXPRESSIONS.MEMBER, memberExpressionRule);
4546
rules.set(EXPRESSIONS.ARRAY, arrayExpressionRule);
47+
rules.set(EXPRESSIONS.LAMBDA, arrowFunctionExpressionRule);
4648

4749
rules.set(DECLARATIONS.VARIABLE, variableDeclarationRule);
4850
rules.set(DECLARATIONS.FUNCTION, functionDeclarationRule);

server/src/rules/memberExpression.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { AST } from "../ast";
22
import { Rule } from "./rule";
33
import { MemberExpression, Node } from "estree"
44
import { DiagnosticSeverity } from "vscode-languageserver";
5-
import { NODES } from "../types";
5+
import { EXPRESSIONS, NODES } from "../types";
66
import { Chapter, Context } from "../types";
77

88
export const memberExpressionRule = new class extends Rule<MemberExpression> {
@@ -13,12 +13,14 @@ export const memberExpressionRule = new class extends Rule<MemberExpression> {
1313
if (!child.computed)
1414
ast.addDiagnostic("No dot abbreviations", DiagnosticSeverity.Error, child.loc!);
1515
else if (child.property.type === NODES.IDENTIFIER && child.property.name === "undefined")
16-
ast.addDiagnostic("Expected integer as array index, got undefined.", DiagnosticSeverity.Error, child.property.loc!);
16+
ast.addDiagnostic("Expected non negative integer as array index, got undefined.", DiagnosticSeverity.Error, child.property.loc!);
1717
else if (child.property.type === NODES.LITERAL) {
1818
if (typeof child.property.value !== "number")
19-
ast.addDiagnostic(`Expected integer as array index, got ${child.property.value === null ? "null" : typeof child.property.value }.`, DiagnosticSeverity.Error, child.property.loc!);
19+
ast.addDiagnostic(`Expected non negative integer as array index, got ${child.property.value === null ? "null" : typeof child.property.value }.`, DiagnosticSeverity.Error, child.property.loc!);
2020
else if (!Number.isSafeInteger(child.property.value))
21-
ast.addDiagnostic("Expected integer as array index, got float.", DiagnosticSeverity.Error, child.property.loc!);
21+
ast.addDiagnostic("Expected non negative integer as array index, got float.", DiagnosticSeverity.Error, child.property.loc!);
2222
}
23+
else if (child.property.type === EXPRESSIONS.UNARY && child.property.operator === "-" && child.property.argument.type === NODES.LITERAL && typeof child.property.argument.value === "number")
24+
ast.addDiagnostic("Expected non negative integer as array index, got negative number.", DiagnosticSeverity.Error, child.property.loc!);
2325
}
2426
}();

server/src/rules/templateLiteral.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import { Context } from "../types";
66

77
export const templateLiteralRule = new class extends Rule<TemplateLiteral> {
88
public process(child: TemplateLiteral, parent: Node, context: Context, ast: AST): void {
9-
if (child.expressions.length > 0)
10-
ast.addDiagnostic("Expressions not allowed in template literal", DiagnosticSeverity.Error, child.loc!);
9+
child.expressions.forEach(expression => {
10+
ast.addDiagnostic("Expressions not allowed in template literal", DiagnosticSeverity.Error, expression.loc!);
11+
})
1112
}
1213
}();

server/src/server.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,7 @@ connection.onInitialize((params: InitializeParams) => {
7878
documentHighlightProvider: true,
7979
documentSymbolProvider: true,
8080
renameProvider: true,
81-
hoverProvider: true,
82-
diagnosticProvider: {
83-
interFileDependencies: false,
84-
workspaceDiagnostics: false
85-
}
81+
hoverProvider: true
8682
}
8783
};
8884
if (hasWorkspaceFolderCapability) {

0 commit comments

Comments
 (0)