Skip to content

Commit

Permalink
Major progress towards auto-completion & intelliSense #34
Browse files Browse the repository at this point in the history
  • Loading branch information
EliotVU committed Nov 8, 2021
1 parent d6b60b4 commit a2c67de
Show file tree
Hide file tree
Showing 12 changed files with 1,602 additions and 1,229 deletions.
2 changes: 2 additions & 0 deletions grammars/UCLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ KW_SELF: 'self';
KW_SUPER: 'super';
KW_POINTER: 'pointer';
KW_EXPANDS: 'expands';
KW_IMPLEMENTS: 'implements';
KW_DEPENDSON: 'dependson';
KW_K2CALL: 'k2call';
KW_K2PURE: 'k2pure';
KW_K2OVERRIDE: 'k2override';
Expand Down
99 changes: 55 additions & 44 deletions grammars/UCParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ identifier
// |'nousercreate'
// |'notplaceable'
// |'safereplace'
// |'dependson'
| 'dependson'
// |'showcategories'
// |'hidecategories'
// |'guid'
Expand Down Expand Up @@ -156,7 +156,7 @@ identifier
| 'k2override'
// |'collapsecategories'
// |'dontcollapsecategories'
// |'implements'
| 'implements'
// |'classgroup'
// |'autoexpandcategories'
// |'autocollapsecategories'
Expand Down Expand Up @@ -260,52 +260,55 @@ classDecl
extendsClause: ('extends' | 'expands') id=qualifiedIdentifier;
withinClause: 'within' id=qualifiedIdentifier;

classModifier: identifier modifierArguments?;
classModifier
:
// in UC3 a class can have a custom native name.
// (kwNATIVE modifierArgument?)
// | kwNATIVEREPLICATION
// | kwLOCALIZED // UC1
// | kwABSTRACT
// | kwPEROBJECTCONFIG
// | kwTRANSIENT
// | kwEXPORT
// | kwNOEXPORT
// | kwNOUSERCREATE
// | kwSAFEREPLACE
// | (kwCONFIG modifierArgument?)
(KW_NATIVE modifierArgument?) #nativeModifier
// | KW_NATIVEREPLICATION
// | KW_LOCALIZED // UC1
// | KW_ABSTRACT
// | KW_PEROBJECTCONFIG
| KW_TRANSIENT #transientModifier
| KW_EXPORT #exportModifier
// | KW_NOEXPORT
// | KW_NOUSERCREATE
// | KW_SAFEREPLACE
// | (KW_CONFIG modifierArgument?)
// // UC2+
// | kwPLACEABLE
// | kwNOTPLACEABLE
// | kwCACHEEXEMPT // UT2004
// | kwHIDEDROPDOWN
// | kwEXPORTSTRUCTS
// | kwINSTANCED
// | kwPARSECONFIG
// | kwEDITINLINENEW
// | kwNOTEDITINLINENEW
// | (kwDEPENDSON modifierArguments)
// | (kwCOLLAPSECATEGORIES modifierArguments)
// | (kwDONTCOLLAPSECATEGORIES modifierArguments?)
// | (kwSHOWCATEGORIES modifierArguments)
// | (kwHIDECATEGORIES modifierArguments)
// | (kwGUID (LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA INTEGER RPAREN))
// | KW_PLACEABLE
// | KW_NOTPLACEABLE
// | KW_CACHEEXEMPT // UT2004
// | KW_HIDEDROPDOWN
// | KW_EXPORTSTRUCTS
// | KW_INSTANCED
// | KW_PARSECONFIG
// | KW_EDITINLINENEW
// | KW_NOTEDITINLINENEW
| (KW_DEPENDSON OPEN_PARENS identifierArguments CLOSE_PARENS) #dependsOnModifier
// | (KW_COLLAPSECATEGORIES modifierArguments)
// | (KW_DONTCOLLAPSECATEGORIES modifierArguments?)
// | (KW_SHOWCATEGORIES modifierArguments)
// | (KW_HIDECATEGORIES modifierArguments)
// | (KW_GUID (LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA INTEGER RPAREN))
// // UC3+
// | kwNATIVEONLY
// | kwNONTRANSIENT
// | kwPEROBJECTLOCALIZED
// | kwDEPRECATED
// | (kwCLASSREDIRECT modifierArguments)
// | (kwDLLBIND modifierArgument)
// | (kwIMPLEMENTS modifierArgument)
// | (kwCLASSGROUP modifierArguments)
// | (kwAUTOEXPANDCATEGORIES modifierArguments)
// | (kwAUTOCOLLAPSECATEGORIES modifierArguments)
// | (kwDONTAUTOCOLLAPSECATEGORIES modifierArguments)
// | (kwDONTSORTCATEGORIES modifierArguments)
// | (kwINHERITS modifierArguments)
// | KW_NATIVEONLY
// | KW_NONTRANSIENT
// | KW_PEROBJECTLOCALIZED
// | KW_DEPRECATED
// | (KW_CLASSREDIRECT modifierArgument)
// | (KW_DLLBIND modifierArgument)
| (KW_IMPLEMENTS OPEN_PARENS qualifiedIdentifierArguments CLOSE_PARENS) #implementsModifier
// | (KW_CLASSGROUP modifierArguments)
// | (KW_AUTOEXPANDCATEGORIES modifierArguments)
// | (KW_AUTOCOLLAPSECATEGORIES modifierArguments)
// | (KW_DONTAUTOCOLLAPSECATEGORIES modifierArguments)
// | (KW_DONTSORTCATEGORIES modifierArguments)
// | (KW_INHERITS modifierArguments)
// // true/false only
// | (kwFORCESCRIPTORDER modifierArgument)
// | (KW_FORCESCRIPTORDER modifierArgument)
// ; //ID (LPARENT ID (COMMA ID)* RPARENT)?
| (identifier modifierArguments?) #unidentifiedModifier
;

modifierValue
: identifier
Expand All @@ -320,6 +323,14 @@ modifierArguments
: OPEN_PARENS (modifierValue COMMA?)* CLOSE_PARENS
;

identifierArguments
: (identifier COMMA?)*
;

qualifiedIdentifierArguments
: (qualifiedIdentifier COMMA?)*
;

constDecl
: 'const' identifier (ASSIGNMENT expr=constValue)? SEMICOLON
;
Expand Down Expand Up @@ -831,7 +842,7 @@ assignmentExpression
primaryExpression
: primaryExpression (OPEN_BRACKET arg=expression? CLOSE_BRACKET) #elementAccessExpression
| primaryExpression '.' classPropertyAccessSpecifier '.' identifier #propertyClassAccessExpression
| primaryExpression '.' identifier #propertyAccessExpression
| primaryExpression '.' identifier? #propertyAccessExpression
| primaryExpression (OPEN_PARENS arguments? CLOSE_PARENS) #callExpression

| 'new' (OPEN_PARENS arguments? CLOSE_PARENS)? expr=primaryExpression #newExpression
Expand Down
58 changes: 39 additions & 19 deletions server/src/UC/Parser/ErrorStrategy.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,48 @@
import { DefaultErrorStrategy, Parser, ParserRuleContext, RecognitionException } from 'antlr4ts';
import { DefaultErrorStrategy, Parser, RecognitionException } from 'antlr4ts';

import { UCParser } from '../antlr/generated/UCParser';

export class UCMissingSemicolonException extends Error {
constructor(private context: ParserRuleContext) {
super();
}
}

export class UCErrorStrategy extends DefaultErrorStrategy {
reportError(recognizer: Parser, e: RecognitionException) {
if (e.expectedTokens && e.expectedTokens.contains(UCParser.SEMICOLON)) {
const token = this.constructToken(
recognizer.inputStream.tokenSource,
UCParser.SEMICOLON, ';',
recognizer.currentToken
);
reportError(recognizer: Parser, e: RecognitionException) {
if (typeof e.expectedTokens === 'undefined') {
super.reportError(recognizer, e);
return;
}

if (e.expectedTokens.contains(UCParser.SEMICOLON)) {
const token = this.constructToken(
recognizer.inputStream.tokenSource,
UCParser.SEMICOLON, ';',
recognizer.currentToken
);

const errorNode = recognizer.createErrorNode(recognizer.context, token);
recognizer.context.addErrorNode(errorNode);
// } else if (e.expectedTokens.contains(UCParser.OPEN_PARENS)) {
// const openToken = this.constructToken(
// recognizer.inputStream.tokenSource,
// UCParser.OPEN_PARENS, '(',
// recognizer.currentToken
// );
// recognizer.context.addErrorNode(recognizer.createErrorNode(recognizer.context, openToken));

const errorNode = recognizer.createErrorNode(recognizer.context, token);
recognizer.context.addErrorNode(errorNode);
}
// const closeToken = this.constructToken(
// recognizer.inputStream.tokenSource,
// UCParser.CLOSE_PARENS, ')',
// recognizer.currentToken
// );
// recognizer.context.addErrorNode(recognizer.createErrorNode(recognizer.context, closeToken));
// } else if (e.expectedTokens.contains(UCParser.CLOSE_PARENS)) {
// const closeToken = this.constructToken(
// recognizer.inputStream.tokenSource,
// UCParser.CLOSE_PARENS, ')',
// recognizer.currentToken
// );
// recognizer.context.addErrorNode(recognizer.createErrorNode(recognizer.context, closeToken));
}

super.reportError(recognizer, e);
}
super.reportError(recognizer, e);
}
}

export const ERROR_STRATEGY = new UCErrorStrategy();
4 changes: 4 additions & 0 deletions server/src/UC/Symbols/MethodSymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ export class UCMethodLikeSymbol extends UCMethodSymbol implements IWithReference
return true;
}

getTypeFlags() {
return UCTypeFlags.Function | UCTypeFlags.Delegate;
}

protected getTypeKeyword(): string {
return '(intrinsic)';
}
Expand Down
10 changes: 10 additions & 0 deletions server/src/UC/Symbols/Package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ export class SymbolsTable<T extends ISymbol> implements ISymbolContainer<T> {
return this.symbols.values() as IterableIterator<C>;
}

*getTypes<C extends T>(type: UCTypeFlags): Generator<C, C[]> {
for (let symbol of this.symbols.values()) {
if ((symbol.getTypeFlags() & type) === 0) {
continue;
}
yield symbol as C;
}
return [];
}

addSymbol(symbol: T): number {
return this.addKey(getSymbolHash(symbol), symbol);
}
Expand Down
28 changes: 28 additions & 0 deletions server/src/UC/Symbols/ScriptStructSymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,34 @@ export class UCScriptStructSymbol extends UCStructSymbol {
return `struct ${this.getPath()}`;
}

getCompletionSymbols<C extends ISymbol>(document: UCDocument, _context: string, type?: UCTypeFlags) {
const symbols: ISymbol[] = [];
for (let child = this.children; child; child = child.next) {
if (typeof type !== 'undefined' && (child.getTypeFlags() & type) === 0) {
continue;
}
if (child.acceptCompletion(document, this)) {
symbols.push(child);
}
}

for (let parent = this.super; parent; parent = parent.super) {
if ((parent.getTypeFlags() & UCTypeFlags.Struct) === 0) {
break;
}

for (let child = parent.children; child; child = child.next) {
if (typeof type !== 'undefined' && (child.getTypeFlags() & type) === 0) {
continue;
}
if (child.acceptCompletion(document, this)) {
symbols.push(child);
}
}
}
return symbols as C[];
}

acceptCompletion(_document: UCDocument, context: UCSymbol): boolean {
return (context instanceof UCPropertySymbol || context instanceof UCMethodSymbol);
}
Expand Down
6 changes: 3 additions & 3 deletions server/src/UC/Symbols/StructSymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ export class UCStructSymbol extends UCFieldSymbol implements ISymbolContainer<IS
return CompletionItemKind.Module;
}

getCompletionSymbols<C extends ISymbol>(document: UCDocument, _context: string, kind?: UCTypeFlags) {
getCompletionSymbols<C extends ISymbol>(document: UCDocument, _context: string, type?: UCTypeFlags) {
const symbols: ISymbol[] = [];
for (let child = this.children; child; child = child.next) {
if (typeof kind !== 'undefined' && child.getTypeFlags() !== kind) {
if (typeof type !== 'undefined' && (child.getTypeFlags() & type) === 0) {
continue;
}
if (child.acceptCompletion(document, this)) {
Expand All @@ -38,7 +38,7 @@ export class UCStructSymbol extends UCFieldSymbol implements ISymbolContainer<IS
let parent = this.super ?? this.outer as UCStructSymbol;
for (; parent; parent = parent.super ?? parent.outer as UCStructSymbol) {
for (let child = parent.children; child; child = child.next) {
if (typeof kind !== 'undefined' && child.getTypeFlags() !== kind) {
if (typeof type !== 'undefined' && (child.getTypeFlags() & type) === 0) {
continue;
}
if (child.acceptCompletion(document, this)) {
Expand Down
Loading

0 comments on commit a2c67de

Please sign in to comment.