assemblyscript icon indicating copy to clipboard operation
assemblyscript copied to clipboard

Emit an error if a custom decorator is not consumed and support nest name for decorator

Open yjhmelody opened this issue 4 years ago • 7 comments

I find the decorator support property access expression.

  parseDecorator(
    tn: Tokenizer
  ): DecoratorNode | null {

    // at '@': Identifier ('.' Identifier)* '(' Arguments

    var startPos = tn.tokenPos;
    if (tn.skipIdentifier()) {
      let name = tn.readIdentifier();
      let expression: Expression = Node.createIdentifierExpression(name, tn.range(startPos, tn.pos));
      while (tn.skip(Token.DOT)) {
        if (tn.skipIdentifier(IdentifierHandling.PREFER)) {
          name = tn.readIdentifier();
          expression = Node.createPropertyAccessExpression(
            expression,
            Node.createIdentifierExpression(name, tn.range()),
            tn.range(startPos, tn.pos)
          );
        } else {
          this.error(
            DiagnosticCode.Identifier_expected,
            tn.range()
          );
          return null;
        }
      }
      let args: Expression[] | null;
      if (tn.skip(Token.OPENPAREN)) {
        args = this.parseArguments(tn);
        if (args) {
          return Node.createDecorator(expression, args, tn.range(startPos, tn.pos));
        }
      } else {
        return Node.createDecorator(expression, null, tn.range(startPos, tn.pos));
      }
    } else {
      this.error(
        DiagnosticCode.Identifier_expected,
        tn.range()
      );
    }
    return null;
  }

But in ast's fromNode, it does not check prefix name, just use the last property.

  export function fromNode(nameNode: Expression): DecoratorKind | string {
    if (nameNode.kind == NodeKind.IDENTIFIER) {
      let nameStr = (<IdentifierExpression>nameNode).text;
      assert(nameStr.length);
      switch (nameStr.charCodeAt(0)) {
//...

So it works like the following code:

@foo.inline
@foo.global 

but I wanna compiled error !!.

Another problem is: We need to impl some precompile tools, but I think the DecoratorKind is not friendly. Whether the parser of decorators is based on table-driven is better, and then provide built-in and custom ? If so, we do not need to alter as internals.

yjhmelody avatar Feb 05 '21 10:02 yjhmelody

Looking at fromNode, it only considers IdentifierExpression, not PropertyAccessExpressions like @foo.inline. So @inline becomes DecoratorKind.INLINE, while @foo.inline becomes DecoratorKind.CUSTOM, which is intended. We still could need a mechanism to emit an error there of course if the custom decorator is never consumed, which transforms would do. One option would be to establish the convention that the transform sets the decorator to CommonFlags.COMPILED, and then a final check is performed after all transforms ran to see if there are remaining custom decorators.

dcodeIO avatar Feb 05 '21 12:02 dcodeIO

Hi, maybe adding a new type CustomDecoratorNode which extends DecoratorNode is better ?

yjhmelody avatar Feb 20 '21 10:02 yjhmelody

I think it can be done without another class, but if it turns out to help, why not :)

dcodeIO avatar Feb 20 '21 11:02 dcodeIO

Hi, can decorators use the property access syntax normally now?

@foo.bar is definitely not equal with @bar.

The transform can distinguish by itself, but it may conflict with the compiler provided if not support property access syntax.

yjhmelody avatar Apr 09 '21 02:04 yjhmelody

@yjhmelody of course, nothing is equal with me

bar avatar Apr 09 '21 04:04 bar

@yjhmelody of course, nothing is equal with me

lol

yjhmelody avatar Apr 09 '21 04:04 yjhmelody

@dcodeIO Hi, How is this feature going now? It will be great to have nest for decorator name e.g.@foo.inline. For different transformer, they could use different namespace to avoid naming confliction. Even you can enforce this specification, if necessary

yjhmelody avatar Feb 08 '23 14:02 yjhmelody