diff --git a/server/src/compiler_analyzer/analyzer.ts b/server/src/compiler_analyzer/analyzer.ts index d81b5b55..196bb2fb 100644 --- a/server/src/compiler_analyzer/analyzer.ts +++ b/server/src/compiler_analyzer/analyzer.ts @@ -1,18 +1,14 @@ // https://www.angelcode.com/angelscript/sdk/docs/manual/doc_expressions.html import { - AccessModifier, funcHeadDestructor, - isFunctionHeadReturnValue, isMemberMethodInPostOp, NodeArgList, NodeAssign, NodeCase, NodeCast, - NodeClass, NodeCondition, NodeDoWhile, - NodeEnum, NodeExpr, NodeExprPostOp, NodeExprPostOp1, @@ -24,31 +20,22 @@ import { NodeFor, NodeFunc, NodeFuncCall, - NodeFuncDef, NodeIf, NodeInitList, - NodeInterface, - NodeIntfMethod, NodeLambda, NodeLiteral, - NodeMixin, NodeName, - NodeNamespace, NodeParamList, NodeReturn, NodeScope, - NodeScript, NodeStatBlock, NodeStatement, NodeSwitch, NodeTry, NodeType, - NodeTypeDef, NodeVar, NodeVarAccess, - NodeVirtualProp, NodeWhile, - ParsedEnumMember, ParsedRange } from "../compiler_parser/nodes"; import { @@ -63,13 +50,10 @@ import {diagnostic} from "../code/diagnostic"; import {LocationInfo, NumberLiterals, TokenKind} from "../compiler_tokenizer/tokens"; import { AnalyzedScope, - copySymbolsInScope, createAnonymousIdentifier, - createSymbolScope, createSymbolScopeAndInsert, findGlobalScope, findScopeShallowly, - findScopeShallowlyOrInsert, findScopeWithParentByNodes, isSymbolConstructorInScope, SymbolScope } from "./symbolScope"; @@ -77,15 +61,12 @@ import {checkFunctionMatch} from "./checkFunction"; import {ParserToken} from "../compiler_parser/parserToken"; import {canTypeConvert, checkTypeMatch, isAllowedToAccessMember} from "./checkType"; import { - getIdentifierInType, getLocationBetween, getNextTokenIfExist, getNodeLocation } from "../compiler_parser/nodesUtils"; import { builtinBoolType, - builtinSetterValueToken, - builtinThisToken, resolvedBuiltinBool, resolvedBuiltinDouble, resolvedBuiltinFloat, @@ -101,12 +82,10 @@ import { isResolvedAutoType, stringifyResolvedType, stringifyResolvedTypes, - TemplateTranslation, - tryInsertSymbolObject + TemplateTranslation } from "./symbolUtils"; import {Mutable} from "../utils/utilities"; import {getGlobalSettings} from "../code/settings"; -import {createVirtualToken} from "../compiler_tokenizer/tokenUtils"; import assert = require("node:assert"); import {ResolvedType} from "./resolvedType"; @@ -352,7 +331,7 @@ function analyzeScope(parentScope: SymbolScope, nodeScope: NodeScope): SymbolSco let found: SymbolScope | undefined = undefined; for (; ;) { found = findScopeShallowly(scopeIterator, nextScope.text); - if (found?.ownerNode?.nodeName === NodeName.Func) found = undefined; + if (found?.linkedNode?.nodeName === NodeName.Func) found = undefined; if (found !== undefined) break; if (i == 0 && scopeIterator.parentScope !== undefined) { // If it is not a global scope, search further up the hierarchy. @@ -391,17 +370,21 @@ function analyzeStatement(scope: SymbolScope, statement: NodeStatement) { case NodeName.If: analyzeIf(scope, statement); break; - case NodeName.For: - analyzeFor(scope, statement); + case NodeName.For: { + const childScope = createSymbolScopeAndInsert(statement, scope, createAnonymousIdentifier()); + analyzeFor(childScope, statement); break; - case NodeName.While: - analyzeWhile(scope, statement); + } + case NodeName.While: { + const childScope = createSymbolScopeAndInsert(statement, scope, createAnonymousIdentifier()); + analyzeWhile(childScope, statement); break; + } case NodeName.Return: analyzeReturn(scope, statement); break; case NodeName.StatBlock: { - const childScope = createSymbolScopeAndInsert(undefined, scope, createAnonymousIdentifier()); + const childScope = createSymbolScopeAndInsert(statement, scope, createAnonymousIdentifier()); analyzeStatBlock(childScope, statement); break; } @@ -409,18 +392,22 @@ function analyzeStatement(scope: SymbolScope, statement: NodeStatement) { break; case NodeName.Continue: break; - case NodeName.DoWhile: - analyzeDoWhile(scope, statement); + case NodeName.DoWhile: { + const childScope = createSymbolScopeAndInsert(statement, scope, createAnonymousIdentifier()); + analyzeDoWhile(childScope, statement); break; + } case NodeName.Switch: analyzeSwitch(scope, statement); break; case NodeName.ExprStat: analyzeExprStat(scope, statement); break; - case NodeName.Try: - analyzeTry(scope, statement); + case NodeName.Try: { + const childScope = createSymbolScopeAndInsert(statement, scope, createAnonymousIdentifier()); + analyzeTry(childScope, statement); break; + } default: break; } @@ -498,17 +485,17 @@ function analyzeReturn(scope: SymbolScope, nodeReturn: NodeReturn) { const returnType = nodeReturn.assign !== undefined ? analyzeAssign(scope, nodeReturn.assign) : undefined; const functionScope = findScopeWithParentByNodes(scope, [NodeName.Func, NodeName.VirtualProp, NodeName.Lambda]); - if (functionScope === undefined || functionScope.ownerNode === undefined) return; + if (functionScope === undefined || functionScope.linkedNode === undefined) return; // TODO: Support for lambda - if (functionScope.ownerNode.nodeName === NodeName.Func) { + if (functionScope.linkedNode.nodeName === NodeName.Func) { let functionReturn = functionScope.parentScope?.symbolMap.get(functionScope.key); if (functionReturn === undefined || functionReturn instanceof SymbolFunction === false) return; // Select suitable overload if there are multiple overloads while (functionReturn.nextOverload !== undefined) { - if (functionReturn.sourceNode === functionScope.ownerNode) break; + if (functionReturn.sourceNode === functionScope.linkedNode) break; functionReturn = functionReturn.nextOverload; } @@ -519,7 +506,7 @@ function analyzeReturn(scope: SymbolScope, nodeReturn: NodeReturn) { } else { checkTypeMatch(returnType, functionReturn.returnType, nodeReturn.nodeRange); } - } else if (functionScope.ownerNode.nodeName === NodeName.VirtualProp) { + } else if (functionScope.linkedNode.nodeName === NodeName.VirtualProp) { const key = functionScope.key; const isGetter = key.startsWith('get_'); if (isGetter === false) { diff --git a/server/src/compiler_analyzer/checkType.ts b/server/src/compiler_analyzer/checkType.ts index 230dce66..a02af175 100644 --- a/server/src/compiler_analyzer/checkType.ts +++ b/server/src/compiler_analyzer/checkType.ts @@ -180,7 +180,7 @@ function canConstructImplicitly( // Search for the constructor of the given type from the scope to which the given type belongs. const constructorScope = findScopeShallowly(destScope, destIdentifier); - if (constructorScope === undefined || constructorScope.ownerNode?.nodeName !== NodeName.Class) return false; + if (constructorScope === undefined || constructorScope.linkedNode?.nodeName !== NodeName.Class) return false; // Search for the constructor of the given type from the scope of the type itself. const constructor = findSymbolShallowly(constructorScope, destIdentifier); @@ -221,7 +221,7 @@ export function isAllowedToAccessMember(checkingScope: SymbolScope, declaredSymb if (declaredSymbol.accessRestriction === AccessModifier.Private) { return isScopeChildOrGrandchild(checkingScope, declaredScope); } else if (declaredSymbol.accessRestriction === AccessModifier.Protected) { - if (declaredScope.ownerNode === undefined) return false; + if (declaredScope.linkedNode === undefined) return false; const checkingOuterScope = findScopeWithParentByNodes(checkingScope, [NodeName.Class, NodeName.Interface]); if (checkingOuterScope === undefined || checkingOuterScope.parentScope === undefined) return false; diff --git a/server/src/compiler_analyzer/symbolObject.ts b/server/src/compiler_analyzer/symbolObject.ts index ce285a2c..09f33ea2 100644 --- a/server/src/compiler_analyzer/symbolObject.ts +++ b/server/src/compiler_analyzer/symbolObject.ts @@ -4,22 +4,16 @@ import { NodeEnum, NodeFunc, NodeFuncDef, - NodeIf, NodeInterface, NodeIntfMethod, - NodeLambda, - NodeName, - NodeVirtualProp + NodeName } from "../compiler_parser/nodes"; import {ParserToken} from "../compiler_parser/parserToken"; -import {ComplementHints} from "./symbolComplement"; -import {TemplateTranslation} from "./symbolUtils"; -import assert = require("node:assert"); import {Mutable} from "../utils/utilities"; import {ResolvedType} from "./resolvedType"; import {SymbolScope} from "./symbolScope"; import {TokenKind} from "../compiler_tokenizer/tokens"; -import {numberTypeSet} from "../compiler_tokenizer/tokenReservedWords"; +import assert = require("node:assert"); /** * The node that serves as the origin of a type declaration. @@ -187,18 +181,6 @@ export type SymbolObject = SymbolType | SymbolFunction | SymbolVariable; // (IF | FOR | WHILE | RETURN | STATBLOCK | BREAK | CONTINUE | DOWHILE | SWITCH | EXPRSTAT | TRY) -/** - * Nodes that can have a scope containing symbols. - */ -export type SymbolOwnerNode = - NodeEnum - | NodeClass - | NodeVirtualProp - | NodeInterface - | NodeFunc - | NodeIf - | NodeLambda; - /** * Information about a symbol that references a symbol declared elsewhere. */ diff --git a/server/src/compiler_analyzer/symbolScope.ts b/server/src/compiler_analyzer/symbolScope.ts index 363e045e..586c8156 100644 --- a/server/src/compiler_analyzer/symbolScope.ts +++ b/server/src/compiler_analyzer/symbolScope.ts @@ -1,16 +1,20 @@ -import { - SymbolOwnerNode, - SymbolFunction, - SymbolObject, - ReferencedSymbolInfo, TypeSourceNode, SymbolType -} from "./symbolObject"; +import {ReferencedSymbolInfo, SymbolFunction, SymbolObject, SymbolType, TypeSourceNode} from "./symbolObject"; import {diagnostic} from "../code/diagnostic"; -import {NodeName} from "../compiler_parser/nodes"; +import { + NodeClass, NodeDoWhile, + NodeEnum, NodeFor, + NodeFunc, + NodeIf, + NodeInterface, + NodeLambda, + NodeName, NodeStatBlock, NodeTry, + NodeVirtualProp, NodeWhile +} from "../compiler_parser/nodes"; import {ParserToken} from "../compiler_parser/parserToken"; import {getPathOfScope} from "./symbolUtils"; import {ComplementHints} from "./symbolComplement"; -import assert = require("node:assert"); import {getGlobalSettings} from "../code/settings"; +import assert = require("node:assert"); export type ScopeMap = Map; @@ -20,17 +24,36 @@ interface RootScopeContext { builtinStringType: SymbolType | undefined; } +/** + * Nodes that can have a scope containing symbols. + */ +export type ScopeLinkedNode = + NodeEnum + | NodeClass + | NodeVirtualProp + | NodeInterface + | NodeFunc + | NodeLambda + + // Statement nodes + | NodeStatBlock + | NodeFor + | NodeWhile + | NodeDoWhile + | NodeIf + | NodeTry; + /** * Represents a scope that contains symbols. */ export class SymbolScope { // A node associated with this scope - private symbolOwnerNode: SymbolOwnerNode | undefined; + private scopeLinkedNode: ScopeLinkedNode | undefined; // The parent scope of this scope. If this is the root scope (global scope), it has the context for the file. private readonly parentOrContext: SymbolScope | RootScopeContext; public constructor( - ownerNode: SymbolOwnerNode | undefined, + linkedNode: ScopeLinkedNode | undefined, parentScope: SymbolScope | undefined, public readonly key: string, public readonly childScopes: ScopeMap, @@ -39,16 +62,16 @@ export class SymbolScope { public readonly completionHints: ComplementHints[], ) { this.parentOrContext = parentScope ?? {builtinStringType: undefined}; - this.symbolOwnerNode = ownerNode; + this.scopeLinkedNode = linkedNode; } public static create(args: { - ownerNode: SymbolOwnerNode | undefined + linkedNode: ScopeLinkedNode | undefined parentScope: SymbolScope | undefined key: string }) { return new SymbolScope( - args.ownerNode, + args.linkedNode, args.parentScope, args.key, new Map(), @@ -62,13 +85,13 @@ export class SymbolScope { return undefined; } - public setOwnerNode(ownerNode: SymbolOwnerNode | undefined) { - assert(this.symbolOwnerNode === undefined); - this.symbolOwnerNode = ownerNode; + public setLinkedNode(node: ScopeLinkedNode | undefined) { + assert(this.scopeLinkedNode === undefined); + this.scopeLinkedNode = node; } - public get ownerNode(): SymbolOwnerNode | undefined { - return this.symbolOwnerNode; + public get linkedNode(): ScopeLinkedNode | undefined { + return this.scopeLinkedNode; } /** @@ -134,7 +157,7 @@ export function findScopeWithParent(scope: SymbolScope, identifier: string): Sym } export function findScopeWithParentByNodes(scope: SymbolScope, nodeCandidates: NodeName[]): SymbolScope | undefined { - if (scope.ownerNode !== undefined && nodeCandidates.includes(scope.ownerNode.nodeName)) return scope; + if (scope.linkedNode !== undefined && nodeCandidates.includes(scope.linkedNode.nodeName)) return scope; if (scope.parentScope === undefined) return undefined; return findScopeWithParentByNodes(scope.parentScope, nodeCandidates); } @@ -144,21 +167,21 @@ export function findScopeShallowly(scope: SymbolScope, identifier: string): Symb } export function createSymbolScope( - ownerNode: SymbolOwnerNode | undefined, parentScope: SymbolScope | undefined, key: string + linkedNode: ScopeLinkedNode | undefined, parentScope: SymbolScope | undefined, key: string ): SymbolScope { return SymbolScope.create({ - ownerNode: ownerNode, + linkedNode: linkedNode, parentScope: parentScope, key: key, }); } export function createSymbolScopeAndInsert( - ownerNode: SymbolOwnerNode | undefined, + linkedNode: ScopeLinkedNode | undefined, parentScope: SymbolScope | undefined, identifier: string, ): SymbolScope { - const scope = createSymbolScope(ownerNode, parentScope, identifier); + const scope = createSymbolScope(linkedNode, parentScope, identifier); parentScope?.childScopes.set(identifier, scope); return scope; } @@ -185,7 +208,7 @@ export class AnalyzedScope { public get pureScope(): SymbolScope { if (this.pureBuffer === undefined) { this.pureBuffer = createSymbolScope( - this.fullScope.ownerNode, + this.fullScope.linkedNode, this.fullScope.parentScope, this.fullScope.key); copySymbolsInScope(this.fullScope, this.pureBuffer, {targetSrcPath: this.path}); @@ -243,7 +266,7 @@ export function copySymbolsInScope(srcScope: SymbolScope, destScope: SymbolScope } } - const destChild = findScopeShallowlyThenInsertByIdentifier(child.ownerNode, destScope, key); + const destChild = findScopeShallowlyThenInsertByIdentifier(child.linkedNode, destScope, key); copySymbolsInScope(child, destChild, option); } } @@ -251,18 +274,18 @@ export function copySymbolsInScope(srcScope: SymbolScope, destScope: SymbolScope /** * Searches for a scope within the given scope that has an identifier matching the provided token. * This search is non-recursive. If no matching scope is found, a new one is created and inserted. - * @param ownerNode The node associated with the scope. + * @param linkedNode The node associated with the scope. * @param scope The scope to search within for a matching child scope. * @param identifierToken The token of the identifier to search for. * @returns The found or newly created scope. */ export function findScopeShallowlyOrInsert( - ownerNode: SymbolOwnerNode | undefined, + linkedNode: ScopeLinkedNode | undefined, scope: SymbolScope, identifierToken: ParserToken ): SymbolScope { - const found = findScopeShallowlyThenInsertByIdentifier(ownerNode, scope, identifierToken.text); - if (ownerNode !== undefined && ownerNode !== found.ownerNode) { + const found = findScopeShallowlyThenInsertByIdentifier(linkedNode, scope, identifierToken.text); + if (linkedNode !== undefined && linkedNode !== found.linkedNode) { // If searching for a non-namespace node, throw an error if it doesn't match the found node. // For example, if a scope for a class 'f' already exists, a scope for a function 'f' cannot be created. diagnostic.addError(identifierToken.location, `Symbol ${identifierToken.text}' is already defined.`); @@ -271,14 +294,14 @@ export function findScopeShallowlyOrInsert( } function findScopeShallowlyThenInsertByIdentifier( - ownerNode: SymbolOwnerNode | undefined, + linkedNode: ScopeLinkedNode | undefined, scope: SymbolScope, identifier: string ): SymbolScope { const found: SymbolScope | undefined = scope.childScopes.get(identifier); - if (found === undefined) return createSymbolScopeAndInsert(ownerNode, scope, identifier); - if (ownerNode === undefined) return found; - if (found.ownerNode === undefined) found.setOwnerNode(ownerNode); + if (found === undefined) return createSymbolScopeAndInsert(linkedNode, scope, identifier); + if (linkedNode === undefined) return found; + if (found.linkedNode === undefined) found.setLinkedNode(linkedNode); return found; } @@ -301,9 +324,9 @@ export function isSymbolConstructorInScope(pair: SymbolAndScope): boolean { const scope = pair.scope; return symbol !== undefined && symbol instanceof SymbolFunction - && scope.ownerNode !== undefined - && scope.ownerNode.nodeName === NodeName.Class - && scope.ownerNode.identifier.text === symbol.declaredPlace.text; + && scope.linkedNode !== undefined + && scope.linkedNode.nodeName === NodeName.Class + && scope.linkedNode.identifier.text === symbol.declaredPlace.text; } export function isScopeChildOrGrandchild(childScope: SymbolScope, parentScope: SymbolScope): boolean { diff --git a/server/src/compiler_analyzer/symbolUtils.ts b/server/src/compiler_analyzer/symbolUtils.ts index 7296dd90..d404fcab 100644 --- a/server/src/compiler_analyzer/symbolUtils.ts +++ b/server/src/compiler_analyzer/symbolUtils.ts @@ -15,8 +15,8 @@ import {ResolvedType} from "./resolvedType"; * It returns undefined if the scope is namespace or etc. */ export function getPathOfScope(scope: SymbolScope): string | undefined { - if (scope.ownerNode === undefined) return undefined; - return scope.ownerNode.nodeRange.start.location.path; + if (scope.linkedNode === undefined) return undefined; + return scope.linkedNode.nodeRange.start.location.path; } /** diff --git a/server/src/formatter/formatter.ts b/server/src/formatter/formatter.ts index 2643d62a..98ec3ce8 100644 --- a/server/src/formatter/formatter.ts +++ b/server/src/formatter/formatter.ts @@ -31,14 +31,14 @@ import { NodeWhile, ReferenceModifier } from "../compiler_parser/nodes"; -import {FormatState, isEditedWrapAt} from "./formatState"; +import {FormatterState, isEditedWrapAt} from "./formatterState"; import {TextEdit} from "vscode-languageserver-types/lib/esm/main"; -import {formatMoveToNonComment, formatMoveUntil, formatMoveUntilNodeStart, formatTargetBy} from "./formatDetail"; +import {formatMoveToNonComment, formatMoveUntil, formatMoveUntilNodeStart, formatTargetBy} from "./formatterDetail"; import {TokenizerToken} from "../compiler_tokenizer/tokens"; import {isRangeInOneLine} from "../compiler_parser/nodesUtils"; // SCRIPT ::= {IMPORT | ENUM | TYPEDEF | CLASS | MIXIN | INTERFACE | FUNCDEF | VIRTPROP | VAR | FUNC | NAMESPACE | ';'} -function formatScript(format: FormatState, nodeScript: NodeScript) { +function formatScript(format: FormatterState, nodeScript: NodeScript) { for (const node of nodeScript) { const name = node.nodeName; @@ -69,7 +69,7 @@ function formatScript(format: FormatState, nodeScript: NodeScript) { } // NAMESPACE ::= 'namespace' IDENTIFIER {'::' IDENTIFIER} '{' SCRIPT '}' -function formatNamespace(format: FormatState, nodeNamespace: NodeNamespace) { +function formatNamespace(format: FormatterState, nodeNamespace: NodeNamespace) { formatMoveUntilNodeStart(format, nodeNamespace); format.pushWrap(); @@ -89,7 +89,7 @@ function formatNamespace(format: FormatState, nodeNamespace: NodeNamespace) { }); } -function formatBraceBlock(format: FormatState, action: () => void, isIndent: boolean = true) { +function formatBraceBlock(format: FormatterState, action: () => void, isIndent: boolean = true) { if (formatTargetBy(format, '{', {connectTail: true}) === false) return; const startLine = format.getCursor().line; @@ -105,7 +105,7 @@ function formatBraceBlock(format: FormatState, action: () => void, isIndent: boo } // ENUM ::= {'shared' | 'external'} 'enum' IDENTIFIER (';' | ('{' IDENTIFIER ['=' EXPR] {',' IDENTIFIER ['=' EXPR]} '}')) -function formatEnum(format: FormatState, nodeEnum: NodeEnum) { +function formatEnum(format: FormatterState, nodeEnum: NodeEnum) { formatMoveUntilNodeStart(format, nodeEnum); format.pushWrap(); @@ -131,7 +131,7 @@ function formatEnum(format: FormatState, nodeEnum: NodeEnum) { } // CLASS ::= {'shared' | 'abstract' | 'final' | 'external'} 'class' IDENTIFIER (';' | ([':' IDENTIFIER {',' IDENTIFIER}] '{' {VIRTPROP | FUNC | VAR | FUNCDEF} '}')) -function formatClass(format: FormatState, nodeClass: NodeClass) { +function formatClass(format: FormatterState, nodeClass: NodeClass) { formatMoveUntilNodeStart(format, nodeClass); format.pushWrap(); @@ -161,7 +161,7 @@ function formatClass(format: FormatState, nodeClass: NodeClass) { } // TYPEDEF ::= 'typedef' PRIMTYPE IDENTIFIER ';' -function formatTypeDef(format: FormatState, typeDef: NodeTypeDef) { +function formatTypeDef(format: FormatterState, typeDef: NodeTypeDef) { formatMoveUntilNodeStart(format, typeDef); format.pushWrap(); @@ -175,9 +175,9 @@ function formatTypeDef(format: FormatState, typeDef: NodeTypeDef) { } // FUNC ::= {'shared' | 'external'} ['private' | 'protected'] [((TYPE ['&']) | '~')] IDENTIFIER PARAMLIST ['const'] FUNCATTR (';' | STATBLOCK) -function formatFunc(format: FormatState, nodeFunc: NodeFunc) { +function formatFunc(format: FormatterState, nodeFunc: NodeFunc) { formatMoveUntilNodeStart(format, nodeFunc); - format.pushWrap(); + format.pushWrap(); // TODO: Move to the caller? formatEntityModifier(format); formatAccessModifier(format); @@ -205,7 +205,7 @@ function formatFunc(format: FormatState, nodeFunc: NodeFunc) { } // {'shared' | 'abstract' | 'final' | 'external'} -function formatEntityModifier(format: FormatState) { +function formatEntityModifier(format: FormatterState) { for (; ;) { const next = formatMoveToNonComment(format); if (next === undefined) return; @@ -216,7 +216,7 @@ function formatEntityModifier(format: FormatState) { } // ['private' | 'protected'] -function formatAccessModifier(format: FormatState) { +function formatAccessModifier(format: FormatterState) { const next = formatMoveToNonComment(format); if (next === undefined) return; if (next.text === 'private' || next.text === 'protected') { @@ -225,7 +225,7 @@ function formatAccessModifier(format: FormatState) { } // INTERFACE ::= {'external' | 'shared'} 'interface' IDENTIFIER (';' | ([':' IDENTIFIER {',' IDENTIFIER}] '{' {VIRTPROP | INTFMTHD} '}')) -function formatInterface(format: FormatState, nodeInterface: NodeInterface) { +function formatInterface(format: FormatterState, nodeInterface: NodeInterface) { formatMoveUntilNodeStart(format, nodeInterface); format.pushWrap(); @@ -251,9 +251,8 @@ function formatInterface(format: FormatState, nodeInterface: NodeInterface) { } // VAR ::= ['private'|'protected'] TYPE IDENTIFIER [( '=' (INITLIST | ASSIGN)) | ARGLIST] {',' IDENTIFIER [( '=' (INITLIST | ASSIGN)) | ARGLIST]} ';' -function formatVar(format: FormatState, nodeVar: NodeVar) { +function formatVar(format: FormatterState, nodeVar: NodeVar) { formatMoveUntilNodeStart(format, nodeVar); - format.pushWrap(); formatAccessModifier(format); @@ -285,7 +284,7 @@ function formatVar(format: FormatState, nodeVar: NodeVar) { } // IMPORT ::= 'import' TYPE ['&'] IDENTIFIER PARAMLIST FUNCATTR 'from' STRING ';' -function formatImport(format: FormatState, nodeImport: NodeImport) { +function formatImport(format: FormatterState, nodeImport: NodeImport) { formatMoveUntilNodeStart(format, nodeImport); format.pushWrap(); @@ -309,7 +308,7 @@ function formatImport(format: FormatState, nodeImport: NodeImport) { } // FUNCDEF ::= {'external' | 'shared'} 'funcdef' TYPE ['&'] IDENTIFIER PARAMLIST ';' -function formatFuncDef(format: FormatState, funcDef: NodeFuncDef) { +function formatFuncDef(format: FormatterState, funcDef: NodeFuncDef) { formatMoveUntilNodeStart(format, funcDef); format.pushWrap(); @@ -329,7 +328,7 @@ function formatFuncDef(format: FormatState, funcDef: NodeFuncDef) { } // VIRTPROP ::= ['private' | 'protected'] TYPE ['&'] IDENTIFIER '{' {('get' | 'set') ['const'] FUNCATTR (STATBLOCK | ';')} '}' -function formatVirtualProp(format: FormatState, virtualProp: NodeVirtualProp) { +function formatVirtualProp(format: FormatterState, virtualProp: NodeVirtualProp) { formatMoveUntilNodeStart(format, virtualProp); format.pushWrap(); @@ -360,7 +359,7 @@ function formatVirtualProp(format: FormatState, virtualProp: NodeVirtualProp) { } // ['const'] FUNCATTR (STATBLOCK | ';') -function formatGetterSetterStatement(format: FormatState, isConst: boolean, statBlock: NodeStatBlock | undefined) { +function formatGetterSetterStatement(format: FormatterState, isConst: boolean, statBlock: NodeStatBlock | undefined) { if (isConst) formatTargetBy(format, 'const', {}); formatFuncAttr(format); @@ -373,7 +372,7 @@ function formatGetterSetterStatement(format: FormatState, isConst: boolean, stat } // MIXIN ::= 'mixin' CLASS -function formatMixin(format: FormatState, mixin: NodeMixin) { +function formatMixin(format: FormatterState, mixin: NodeMixin) { formatMoveUntilNodeStart(format, mixin); format.pushWrap(); @@ -383,7 +382,7 @@ function formatMixin(format: FormatState, mixin: NodeMixin) { } // INTFMTHD ::= TYPE ['&'] IDENTIFIER PARAMLIST ['const'] ';' -function formatIntfMethod(format: FormatState, intfMethod: NodeIntfMethod) { +function formatIntfMethod(format: FormatterState, intfMethod: NodeIntfMethod) { formatMoveUntilNodeStart(format, intfMethod); format.pushWrap(); @@ -401,7 +400,7 @@ function formatIntfMethod(format: FormatState, intfMethod: NodeIntfMethod) { } // STATBLOCK ::= '{' {VAR | STATEMENT} '}' -function formatStatBlock(format: FormatState, statBlock: NodeStatBlock) { +function formatStatBlock(format: FormatterState, statBlock: NodeStatBlock) { formatMoveUntilNodeStart(format, statBlock); const isOneLine = isRangeInOneLine(statBlock.nodeRange); @@ -420,7 +419,7 @@ function formatStatBlock(format: FormatState, statBlock: NodeStatBlock) { } // PARAMLIST ::= '(' ['void' | (TYPE TYPEMOD [IDENTIFIER] ['=' EXPR] {',' TYPE TYPEMOD [IDENTIFIER] ['=' EXPR]})] ')' -function formatParamList(format: FormatState, paramList: NodeParamList) { +function formatParamList(format: FormatterState, paramList: NodeParamList) { formatParenthesesBlock(format, () => { if (paramList.length === 0 && formatMoveToNonComment(format)?.text === 'void') { formatTargetBy(format, 'void', {}); @@ -445,7 +444,7 @@ function formatParamList(format: FormatState, paramList: NodeParamList) { }); } -function formatParenthesesBlock(format: FormatState, action: () => void, condenseLeft: boolean = true) { +function formatParenthesesBlock(format: FormatterState, action: () => void, condenseLeft: boolean = true) { if (formatTargetBy(format, '(', {condenseLeft: condenseLeft, condenseRight: true}) === false) return; format.pushIndent(); @@ -456,7 +455,7 @@ function formatParenthesesBlock(format: FormatState, action: () => void, condens } // TYPEMOD ::= ['&' ['in' | 'out' | 'inout']] -function formatTypeMod(format: FormatState) { +function formatTypeMod(format: FormatterState) { const next = formatMoveToNonComment(format); if (next === undefined) return; if (next.text === '&') { @@ -471,7 +470,7 @@ function formatTypeMod(format: FormatState) { } // TYPE ::= ['const'] SCOPE DATATYPE ['<' TYPE {',' TYPE} '>'] { ('[' ']') | ('@' ['const']) } -function formatType(format: FormatState, nodeType: NodeType) { +function formatType(format: FormatterState, nodeType: NodeType) { formatMoveUntilNodeStart(format, nodeType); if (nodeType.isConst) formatTargetBy(format, 'const', {}); @@ -496,7 +495,7 @@ function formatType(format: FormatState, nodeType: NodeType) { } // ['<' TYPE {',' TYPE} '>'] -function formatTypeTemplates(format: FormatState, templates: NodeType[]) { +function formatTypeTemplates(format: FormatterState, templates: NodeType[]) { if (templates.length === 0) return; formatChevronsBlock(format, () => { @@ -507,7 +506,7 @@ function formatTypeTemplates(format: FormatState, templates: NodeType[]) { }); } -function formatChevronsBlock(format: FormatState, action: () => void) { +function formatChevronsBlock(format: FormatterState, action: () => void) { if (formatTargetBy(format, '<', {condenseSides: true}) === false) return; format.pushIndent(); @@ -518,7 +517,7 @@ function formatChevronsBlock(format: FormatState, action: () => void) { } // INITLIST ::= '{' [ASSIGN | INITLIST] {',' [ASSIGN | INITLIST]} '}' -function formatInitList(format: FormatState, initList: NodeInitList) { +function formatInitList(format: FormatterState, initList: NodeInitList) { formatMoveUntilNodeStart(format, initList); formatBraceBlock(format, () => { @@ -536,7 +535,7 @@ function formatInitList(format: FormatState, initList: NodeInitList) { } // SCOPE ::= ['::'] {IDENTIFIER '::'} [IDENTIFIER ['<' TYPE {',' TYPE} '>'] '::'] -function formatScope(format: FormatState, scope: NodeScope) { +function formatScope(format: FormatterState, scope: NodeScope) { formatMoveUntilNodeStart(format, scope); if (scope.isGlobal) formatTargetBy(format, '::', {condenseSides: true}); @@ -549,7 +548,7 @@ function formatScope(format: FormatState, scope: NodeScope) { } // DATATYPE ::= (IDENTIFIER | PRIMTYPE | '?' | 'auto') -function formatDataType(format: FormatState, dataType: NodeDataType) { +function formatDataType(format: FormatterState, dataType: NodeDataType) { formatMoveUntilNodeStart(format, dataType); formatTargetBy(format, dataType.identifier.text, {}); @@ -558,7 +557,7 @@ function formatDataType(format: FormatState, dataType: NodeDataType) { // PRIMTYPE ::= 'void' | 'int' | 'int8' | 'int16' | 'int32' | 'int64' | 'uint' | 'uint8' | 'uint16' | 'uint32' | 'uint64' | 'float' | 'double' | 'bool' // FUNCATTR ::= {'override' | 'final' | 'explicit' | 'property'} -function formatFuncAttr(format: FormatState) { +function formatFuncAttr(format: FormatterState) { for (; ;) { const next = formatMoveToNonComment(format); if (next === undefined) return; @@ -569,7 +568,7 @@ function formatFuncAttr(format: FormatState) { } // STATEMENT ::= (IF | FOR | WHILE | RETURN | STATBLOCK | BREAK | CONTINUE | DOWHILE | SWITCH | EXPRSTAT | TRY) -function formatStatement(format: FormatState, statement: NodeStatement, canIndent: boolean = false) { +function formatStatement(format: FormatterState, statement: NodeStatement, canIndent: boolean = false) { const isIndented = canIndent && statement.nodeName !== NodeName.StatBlock; if (isIndented) format.pushIndent(); @@ -613,7 +612,7 @@ function formatStatement(format: FormatState, statement: NodeStatement, canInden } // SWITCH ::= 'switch' '(' ASSIGN ')' '{' {CASE} '}' -function formatSwitch(format: FormatState, nodeSwitch: NodeSwitch) { +function formatSwitch(format: FormatterState, nodeSwitch: NodeSwitch) { formatMoveUntilNodeStart(format, nodeSwitch); formatTargetBy(format, 'switch', {}); @@ -630,7 +629,7 @@ function formatSwitch(format: FormatState, nodeSwitch: NodeSwitch) { } // BREAK ::= 'break' ';' -function formatBreak(format: FormatState, nodeBreak: NodeBreak) { +function formatBreak(format: FormatterState, nodeBreak: NodeBreak) { formatMoveUntilNodeStart(format, nodeBreak); formatTargetBy(format, 'break', {}); @@ -639,7 +638,7 @@ function formatBreak(format: FormatState, nodeBreak: NodeBreak) { } // FOR ::= 'for' '(' (VAR | EXPRSTAT) EXPRSTAT [ASSIGN {',' ASSIGN}] ')' STATEMENT -function formatFor(format: FormatState, nodeFor: NodeFor) { +function formatFor(format: FormatterState, nodeFor: NodeFor) { formatMoveUntilNodeStart(format, nodeFor); formatTargetBy(format, 'for', {}); @@ -662,7 +661,7 @@ function formatFor(format: FormatState, nodeFor: NodeFor) { } // WHILE ::= 'while' '(' ASSIGN ')' STATEMENT -function formatWhile(format: FormatState, nodeWhile: NodeWhile) { +function formatWhile(format: FormatterState, nodeWhile: NodeWhile) { formatMoveUntilNodeStart(format, nodeWhile); formatTargetBy(format, 'while', {}); @@ -675,7 +674,7 @@ function formatWhile(format: FormatState, nodeWhile: NodeWhile) { } // DOWHILE ::= 'do' STATEMENT 'while' '(' ASSIGN ')' ';' -function formatDoWhile(format: FormatState, doWhile: NodeDoWhile) { +function formatDoWhile(format: FormatterState, doWhile: NodeDoWhile) { formatMoveUntilNodeStart(format, doWhile); formatTargetBy(format, 'do', {}); @@ -692,7 +691,7 @@ function formatDoWhile(format: FormatState, doWhile: NodeDoWhile) { } // IF ::= 'if' '(' ASSIGN ')' STATEMENT ['else' STATEMENT] -function formatIf(format: FormatState, nodeIf: NodeIf) { +function formatIf(format: FormatterState, nodeIf: NodeIf) { formatMoveUntilNodeStart(format, nodeIf); formatTargetBy(format, 'if', {}); @@ -712,14 +711,14 @@ function formatIf(format: FormatState, nodeIf: NodeIf) { } // CONTINUE ::= 'continue' ';' -function formatContinue(format: FormatState, nodeContinue: NodeContinue) { +function formatContinue(format: FormatterState, nodeContinue: NodeContinue) { formatMoveUntilNodeStart(format, nodeContinue); formatTargetBy(format, 'continue', {}); formatTargetBy(format, ';', {condenseLeft: true, connectTail: true}); } // EXPRSTAT ::= [ASSIGN] ';' -function formatExprStat(format: FormatState, exprStat: NodeExprStat) { +function formatExprStat(format: FormatterState, exprStat: NodeExprStat) { formatMoveUntilNodeStart(format, exprStat); if (exprStat.assign !== undefined) formatAssign(format, exprStat.assign); @@ -728,7 +727,7 @@ function formatExprStat(format: FormatState, exprStat: NodeExprStat) { } // TRY ::= 'try' STATBLOCK 'catch' STATBLOCK -function formatTry(format: FormatState, nodeTry: NodeTry) { +function formatTry(format: FormatterState, nodeTry: NodeTry) { formatMoveUntilNodeStart(format, nodeTry); formatTargetBy(format, 'try', {}); @@ -741,7 +740,7 @@ function formatTry(format: FormatState, nodeTry: NodeTry) { } // RETURN ::= 'return' [ASSIGN] ';' -function formatReturn(format: FormatState, nodeReturn: NodeReturn) { +function formatReturn(format: FormatterState, nodeReturn: NodeReturn) { formatMoveUntilNodeStart(format, nodeReturn); formatTargetBy(format, 'return', {}); @@ -758,7 +757,7 @@ function formatReturn(format: FormatState, nodeReturn: NodeReturn) { } // CASE ::= (('case' EXPR) | 'default') ':' {STATEMENT} -function formatCase(format: FormatState, nodeCase: NodeCase) { +function formatCase(format: FormatterState, nodeCase: NodeCase) { formatMoveUntilNodeStart(format, nodeCase); if (nodeCase.expr !== undefined) { @@ -778,7 +777,7 @@ function formatCase(format: FormatState, nodeCase: NodeCase) { } // EXPR ::= EXPRTERM {EXPROP EXPRTERM} -function formatExpr(format: FormatState, nodeExpr: NodeExpr) { +function formatExpr(format: FormatterState, nodeExpr: NodeExpr) { formatMoveUntilNodeStart(format, nodeExpr); formatExprTerm(format, nodeExpr.head); @@ -795,7 +794,7 @@ function formatExpr(format: FormatState, nodeExpr: NodeExpr) { } // EXPRTERM ::= ([TYPE '='] INITLIST) | ({EXPRPREOP} EXPRVALUE {EXPRPOSTOP}) -function formatExprTerm(format: FormatState, exprTerm: NodeExprTerm) { +function formatExprTerm(format: FormatterState, exprTerm: NodeExprTerm) { formatMoveUntilNodeStart(format, exprTerm); if (exprTerm.exprTerm === 1) { @@ -820,7 +819,7 @@ function formatExprTerm(format: FormatState, exprTerm: NodeExprTerm) { } // EXPRVALUE ::= 'void' | CONSTRUCTCALL | FUNCCALL | VARACCESS | CAST | LITERAL | '(' ASSIGN ')' | LAMBDA -function formatExprValue(format: FormatState, exprValue: NodeExprValue) { +function formatExprValue(format: FormatterState, exprValue: NodeExprValue) { // formatMoveUntilNodeStart(formatter, exprValue); if (exprValue.nodeName === NodeName.ConstructCall) { @@ -843,7 +842,7 @@ function formatExprValue(format: FormatState, exprValue: NodeExprValue) { } // CONSTRUCTCALL ::= TYPE ARGLIST -function formatConstructCall(format: FormatState, constructCall: NodeConstructCall) { +function formatConstructCall(format: FormatterState, constructCall: NodeConstructCall) { formatMoveUntilNodeStart(format, constructCall); formatType(format, constructCall.type); @@ -854,7 +853,7 @@ function formatConstructCall(format: FormatState, constructCall: NodeConstructCa // EXPRPREOP ::= '-' | '+' | '!' | '++' | '--' | '~' | '@' // EXPRPOSTOP ::= ('.' (FUNCCALL | IDENTIFIER)) | ('[' [IDENTIFIER ':'] ASSIGN {',' [IDENTIFIER ':' ASSIGN} ']') | ARGLIST | '++' | '--' -function formatExprPostOp(format: FormatState, postOp: NodeExprPostOp) { +function formatExprPostOp(format: FormatterState, postOp: NodeExprPostOp) { formatMoveUntilNodeStart(format, postOp); format.pushIndent(); @@ -892,7 +891,7 @@ function formatExprPostOp(format: FormatState, postOp: NodeExprPostOp) { format.popIndent(); } -function formatBracketsBlock(format: FormatState, action: () => void) { +function formatBracketsBlock(format: FormatterState, action: () => void) { if (formatTargetBy(format, '[', {condenseSides: true}) === false) return; format.pushIndent(); @@ -903,7 +902,7 @@ function formatBracketsBlock(format: FormatState, action: () => void) { } // CAST ::= 'cast' '<' TYPE '>' '(' ASSIGN ')' -function formatCast(format: FormatState, nodeCast: NodeCast) { +function formatCast(format: FormatterState, nodeCast: NodeCast) { formatMoveUntilNodeStart(format, nodeCast); formatTargetBy(format, 'cast', {}); @@ -918,7 +917,7 @@ function formatCast(format: FormatState, nodeCast: NodeCast) { } // LAMBDA ::= 'function' '(' [[TYPE TYPEMOD] [IDENTIFIER] {',' [TYPE TYPEMOD] [IDENTIFIER]}] ')' STATBLOCK -function formatLambda(format: FormatState, nodeLambda: NodeLambda) { +function formatLambda(format: FormatterState, nodeLambda: NodeLambda) { formatMoveUntilNodeStart(format, nodeLambda); formatTargetBy(format, 'function', {}); @@ -943,7 +942,7 @@ function formatLambda(format: FormatState, nodeLambda: NodeLambda) { // LITERAL ::= NUMBER | STRING | BITS | 'true' | 'false' | 'null' // FUNCCALL ::= SCOPE IDENTIFIER ARGLIST -function formatFuncCall(format: FormatState, funcCall: NodeFuncCall) { +function formatFuncCall(format: FormatterState, funcCall: NodeFuncCall) { formatMoveUntilNodeStart(format, funcCall); if (funcCall.scope !== undefined) { @@ -956,7 +955,7 @@ function formatFuncCall(format: FormatState, funcCall: NodeFuncCall) { } // VARACCESS ::= SCOPE IDENTIFIER -function formatVarAccess(format: FormatState, varAccess: NodeVarAccess) { +function formatVarAccess(format: FormatterState, varAccess: NodeVarAccess) { formatMoveUntilNodeStart(format, varAccess); if (varAccess.scope !== undefined) { @@ -969,7 +968,7 @@ function formatVarAccess(format: FormatState, varAccess: NodeVarAccess) { } // ARGLIST ::= '(' [IDENTIFIER ':'] ASSIGN {',' [IDENTIFIER ':'] ASSIGN} ')' -function formatArgList(format: FormatState, nodeArgList: NodeArgList) { +function formatArgList(format: FormatterState, nodeArgList: NodeArgList) { formatMoveUntilNodeStart(format, nodeArgList); formatParenthesesBlock(format, () => { @@ -988,7 +987,7 @@ function formatArgList(format: FormatState, nodeArgList: NodeArgList) { } // ASSIGN ::= CONDITION [ ASSIGNOP ASSIGN ] -function formatAssign(format: FormatState, nodeAssign: NodeAssign) { +function formatAssign(format: FormatterState, nodeAssign: NodeAssign) { formatMoveUntilNodeStart(format, nodeAssign); formatCondition(format, nodeAssign.condition); @@ -1001,7 +1000,7 @@ function formatAssign(format: FormatState, nodeAssign: NodeAssign) { } // CONDITION ::= EXPR ['?' ASSIGN ':' ASSIGN] -function formatCondition(format: FormatState, condition: NodeCondition) { +function formatCondition(format: FormatterState, condition: NodeCondition) { formatMoveUntilNodeStart(format, condition); formatExpr(format, condition.expr); @@ -1033,7 +1032,7 @@ function formatCondition(format: FormatState, condition: NodeCondition) { // WHITESPACE ::= single token: spaces, tab, carriage return, line feed, and UTF8 byte-order-mark export function formatDocument(content: string, tokens: TokenizerToken[], ast: NodeScript): TextEdit[] { - const format = new FormatState(content, tokens, ast); + const format = new FormatterState(content, tokens, ast); formatScript(format, ast); formatMoveUntil(format, {line: format.textLines.length, character: 0}); diff --git a/server/src/formatter/formatDetail.ts b/server/src/formatter/formatterDetail.ts similarity index 90% rename from server/src/formatter/formatDetail.ts rename to server/src/formatter/formatterDetail.ts index 59ba60d8..fb29bdf1 100644 --- a/server/src/formatter/formatDetail.ts +++ b/server/src/formatter/formatterDetail.ts @@ -1,5 +1,5 @@ import {Position} from "vscode-languageserver"; -import {FormatState, stepCursorAlongLines} from "./formatState"; +import {FormatterState, stepCursorAlongLines} from "./formatterState"; import {TokenizerToken, TokenKind} from "../compiler_tokenizer/tokens"; import {NodesBase} from "../compiler_parser/nodes"; import {tracer} from "../code/tracer"; @@ -10,7 +10,7 @@ function isNullOrWhitespace(char: string | undefined): boolean { return /\s/.test(char); } -function walkBackUntilWhitespace(format: FormatState, cursor: Position): Position { +function walkBackUntilWhitespace(format: FormatterState, cursor: Position): Position { const line = cursor.line; let character = cursor.character; @@ -22,7 +22,7 @@ function walkBackUntilWhitespace(format: FormatState, cursor: Position): Positio return {line: line, character: character}; } -function formatTokenWithSpace(format: FormatState, frontToken: TokenizerToken) { +function formatTokenWithSpace(format: FormatterState, frontToken: TokenizerToken) { const spaceEnd: Position = {line: frontToken.location.start.line, character: frontToken.location.start.character}; const spaceStart: Position = walkBackUntilWhitespace(format, spaceEnd); @@ -61,11 +61,11 @@ export interface FormatTargetOption { connectTail?: boolean; } -export function formatMoveUntilNodeStart(format: FormatState, node: NodesBase) { +export function formatMoveUntilNodeStart(format: FormatterState, node: NodesBase) { formatMoveUntil(format, node.nodeRange.start.location.start); } -export function formatMoveUntil(format: FormatState, destination: Position) { +export function formatMoveUntil(format: FormatterState, destination: Position) { let cursor = format.getCursor(); while (format.isFinished() === false) { if (cursor.line >= format.textLines.length) { @@ -104,7 +104,7 @@ export function formatMoveUntil(format: FormatState, destination: Position) { } } -export function formatMoveToNonComment(format: FormatState): TokenizerToken | undefined { +export function formatMoveToNonComment(format: FormatterState): TokenizerToken | undefined { let cursor = format.getCursor(); while (format.isFinished() === false) { const next = format.map.getTokenAt(cursor); @@ -122,7 +122,7 @@ export function formatMoveToNonComment(format: FormatState): TokenizerToken | un return undefined; } -export function formatTargetBy(format: FormatState, target: string, option: FormatTargetOption): boolean { +export function formatTargetBy(format: FormatterState, target: string, option: FormatTargetOption): boolean { let cursor = format.getCursor(); while (format.isFinished() === false) { const next = format.map.getTokenAt(cursor); @@ -151,7 +151,7 @@ function getMaxBlankLines(): number { return Math.max(1, getGlobalSettings().formatter.maxBlankLines); } -function formatBlankLines(format: FormatState, startLine: number, endLine: number) { +function formatBlankLines(format: FormatterState, startLine: number, endLine: number) { for (let i = startLine; i <= endLine; i++) { if (/^\s*$/.test(format.textLines[i]) === false) { tracer.verbose(`Not a blank line at ${i}`); @@ -167,7 +167,7 @@ function formatBlankLines(format: FormatState, startLine: number, endLine: numbe } function executeFormatTargetWith( - format: FormatState, + format: FormatterState, target: string, option: FormatTargetOption, cursor: Position, diff --git a/server/src/formatter/formatState.ts b/server/src/formatter/formatterState.ts similarity index 99% rename from server/src/formatter/formatState.ts rename to server/src/formatter/formatterState.ts index 0efa2af1..efc2e1ea 100644 --- a/server/src/formatter/formatState.ts +++ b/server/src/formatter/formatterState.ts @@ -17,7 +17,7 @@ function getIndentUnit() { } } -export class FormatState { +export class FormatterState { private resultEdits: TextEdit[] = []; private cursor: Position = {line: 0, character: 0}; diff --git a/server/src/services/completion.ts b/server/src/services/completion.ts index 97d95372..6f121061 100644 --- a/server/src/services/completion.ts +++ b/server/src/services/completion.ts @@ -54,7 +54,7 @@ function getCompletionSymbolsInScope(scope: SymbolScope): CompletionItem[] { // Completion of namespace for (const [childName, childScope] of scope.childScopes) { - if (childScope.ownerNode !== undefined) continue; + if (childScope.linkedNode !== undefined) continue; if (isAnonymousIdentifier(childName)) continue; items.push({ label: childName,