Godot: Anotações em GDScript

Criado em 21 jul. 2018  ·  45Comentários  ·  Fonte: godotengine/godot

Cerca de um ano atrás, houve um PR adicionando anotações para GDScript (# 9469). Ele foi rejeitado principalmente porque não havia uso direto para ele (nenhum dado na árvore de análise, apenas ferramentas de terceiros fariam uso dele).

Esta proposta é adicionar algum uso para anotações de uma forma que torne o GDScript mais extensível sem hackear mais palavras-chave nele.

Para quais anotações podem ser usadas?

  • export dicas. No momento, ele usa uma sintaxe personalizada para cada tipo. Com anotações, ele pode definir diretamente o uso e a dica para PropertyInfo, fazendo melhor uso de novas adições ao Inspetor sem ter que hackear uma nova sintaxe no analisador GDScript.
    Para ser claro, eu deixaria a palavra-chave export , apenas as dicas passariam para as anotações. O tipo pode ser definido com dicas de tipo.
  • Isso inclui categorias para export também (# 4378, # 10303).
  • Substitua a palavra-chave onready por uma anotação.
  • Desativando certos avisos. # 19993 adicionar avisos com uma sintaxe ad-hoc para desativá-los, mas poderia usar anotações em seu lugar.
  • setget (é uma sintaxe meio estranha quando você quer apenas o getter).
  • Palavras-chave RPC ( master , slave , sync , remote ).
  • Novas instruções de pré-processador, como fazer uma função compilar apenas no editor (com tool ) ou apenas no modo de depuração (relacionado a # 12837).
  • Discussão eventual da nova sintaxe (como o sinal a ser emitido quando a variável muda: # 6491).
  • Talvez a possibilidade de adicionar "decoradores" personalizados.

Vantagens
Cada vez que uma nova palavra-chave é adicionada, são necessárias alterações no tokenizer e analisador GDScript para manipulá-la. Em particular, a análise export é bastante complicada e é misturada com outra análise relacionada à classe.

Com as anotações, menos trabalho seria feito para adicionar um determinado atributo (como export, setget, onready), em vez disso, seria necessário apenas verificar quais anotações estão presentes.

Desvantagens
Adicionar suporte de anotação exigiria mais mudanças no analisador do que qualquer palavra-chave sozinha. Também pode influenciar as pessoas a sugerir novos recursos como "apenas uma anotação".

Sintaxe
Não tenho nenhuma preferência particular por sintaxe, mas imagino algo como decoradores Python. Pode ser confuso para usuários de Python, já que anotações não são o mesmo que decoradores.

<strong i="41">@onready</strong>
var my_sprite = $Sprite

Para passar argumentos, pode funcionar como funções:

@export_hint(ENUM)
@export_hint_string("Attack,Defense")
export var my_enum : int = 0

Talvez sem parênteses:

<strong i="48">@export_hint</strong> ENUM
<strong i="49">@export_hint_string</strong> "Attack,Defense"
export var my_enum : int = 0

Ou talvez use parâmetros nomeados (e evite a palavra-chave):

<strong i="53">@export</strong> type=String hint=MULTILINE
var my_text = ""

Ou outra coisa.

Anotações personalizadas
Anotações desconhecidas serão simplesmente ignoradas (talvez com um aviso). Portanto, ferramentas de terceiros podem analisar as anotações para oferecer outros recursos, como geração de documentação.

Também é possível adicionar uma API de introspecção: get_method_annotations() , get_property_annotations() ou algo parecido. Dessa forma, os plug-ins que, digamos, esperam scripts podem usar anotações para decidir qual método chamar em vez de usar um nome embutido em código.

archived discussion feature proposal gdscript

Comentários muito úteis

por que a sintaxe do gdscript está sendo modificada tão fortemente? foi originalmente projetado para ser simples, fácil de aprender e intuitivo. Temo que com todas essas novas adições (gds digitados, anotações), vai se tornar muito confuso para novos desenvolvedores.

A maioria (senão todas) das alterações de sintaxe do GDScript são compatíveis com o código antigo. O objetivo principal é aumentar a produtividade dos desenvolvedores usando GDScript, por exemplo:

  • match instruções
  • onready variáveis ​​(que eram novas em 2.x) concretizam um padrão que era freqüentemente usado, ou seja, inicializar variáveis ​​em _ready .
  • O GDScript digitado permite que os desenvolvedores finalmente descansem sabendo que nenhum erro de tipo errado acontecerá, e permite que eles se beneficiem de um preenchimento automático melhor ao mesmo tempo. É opcional, então os novatos não precisam aprender no primeiro jogo.

Eu apenas sinto que pode haver uma possível desconexão entre os desenvolvedores de jogos reais e os contribuidores.

Esta é uma comunidade aberta. Os desenvolvedores de jogos são convidados a vir e expressar sua opinião, assim como você fez. De qualquer forma, muito tempo vai passar antes que as anotações se tornem realidade.

[...] só temo que gds se distancie cada vez mais de sua simplicidade, só isso. já é mais do que suficiente ...

Se já fosse bom o suficiente, não receberíamos solicitações de recursos para ele.

além disso, ter 3 linhas para uma palavra-chave de exportação é muito complicado, em comparação com apenas especificar tudo em uma linha. por exemplo: onready var my_sprite = $ Sprite é muito mais limpo

A sintaxe ainda não foi finalizada. É bem provável que ele não substitua onready e export palavras-chave imediatamente.

Todos 45 comentários

Para que eu esteja entendendo as anotações personalizadas corretamente, eu poderia ter algo assim:

<strong i="6">@description</strong> "Adds two numbers and returns the result."
<strong i="7">@parameter</strong> name=num1 type=float description="The first number"
<strong i="8">@parameter</strong> name=num2 type=float description="The second number"
<strong i="9">@returns</strong> type=float description="num1 and num2 added together"
func add(num1, num2):
    return num1 + num2

E eu poderia chamar uma função, digamos get_annotations("add") , que retornaria essas anotações? Mesmo que essas anotações não sejam reconhecidas por Godot como alguma palavra-chave / anotação embutida?

@ LikeLakers2 sim, esse é o ponto principal.

Eu gosto disso, não sei qual é a implementação por trás, mas no código GDscript ficaria muito mais limpo do que parece agora. Especialmente para o exemplo setget.

Isso é muito útil, mas deve permitir instruções de uma única linha para facilitar a leitura. Por exemplo,
<strong i="6">@onready</strong> var a = $A deve ser permitido. Caso contrário, isso adiciona uma tonelada de novas linhas e, neste caso, desperdiçaria a utilidade de onready.

Algo como

<strong i="10">@onready</strong>
    var a = $A
    var b = $B
    var c = $C

seria útil aplicar a mesma anotação a várias instruções.

Além disso, dois pontos podem ser usados ​​para indicar onde termina a anotação e onde as instruções afetadas começam, para ser consistente com o resto do GDScript.

Se as anotações puderem ser analisadas com um início e um fim claros, não há necessidade de ponto-e-vírgula e podem ser colocadas na mesma linha, se necessário (se usarem '()', por exemplo, ou sem argumento)

Eu não acho que vnen pretendia remover palavras-chave de atalho antigas?

Ter um marcador de texto também pode ajudar.

Atrasado para a festa aqui, mas muito interessado em como isso pode fornecer categorias para exportar vars e criar divisões de script de ferramenta / depuração?

Colocando provisoriamente o roadmap 3.2, eu realmente gostaria de ver isso implementado mais cedo ou mais tarde para fornecer melhorias de usabilidade para o editor.

#### opinião impopular recebida:

por que a sintaxe do gdscript está sendo modificada tão fortemente? foi originalmente projetado para ser simples, fácil de aprender e intuitivo. Temo que com todas essas novas adições (gds digitados, anotações), vai se tornar muito confuso para novos desenvolvedores. por exemplo, se uma nova pessoa em godot assistisse a um tutorial e visse o código que está na postagem de LikeLakers2, imagino que isso faria sua cabeça explodir. se houvesse alguma coisa, eles teriam que fazer um monte de perguntas sobre isso / como funciona, etc.

Eu entendo totalmente o amor de todos por gds e como os contribuidores querem torná-lo melhor, etc. Eu apenas sinto que pode haver uma possível desconexão entre os desenvolvedores de jogos reais e os contribuidores (não estou dizendo que contribuidores não são desenvolvedores de jogos, apenas dizendo como alguns recursos não são realmente necessários). nem todo mundo precisa utilizar esses recursos. só temo que o gds se distancie cada vez mais de sua simplicidade, só isso. já é mais do que suficiente ...

além disso, ter 3 linhas para uma palavra-chave de exportação é muito complicado, em comparação com apenas especificar tudo em uma linha. por exemplo: onready var my_sprite = $Sprite é muito mais limpo (para mim, pelo menos)

e com relação ao ponto # 4, isso pode ser feito no editor AFAIK. além disso, imo, ter anotações em todo o lugar no código para 'desativar certos avisos' pode levar a um código muito confuso

por que a sintaxe do gdscript está sendo modificada tão fortemente? foi originalmente projetado para ser simples, fácil de aprender e intuitivo. Temo que com todas essas novas adições (gds digitados, anotações), vai se tornar muito confuso para novos desenvolvedores.

A maioria (senão todas) das alterações de sintaxe do GDScript são compatíveis com o código antigo. O objetivo principal é aumentar a produtividade dos desenvolvedores usando GDScript, por exemplo:

  • match instruções
  • onready variáveis ​​(que eram novas em 2.x) concretizam um padrão que era freqüentemente usado, ou seja, inicializar variáveis ​​em _ready .
  • O GDScript digitado permite que os desenvolvedores finalmente descansem sabendo que nenhum erro de tipo errado acontecerá, e permite que eles se beneficiem de um preenchimento automático melhor ao mesmo tempo. É opcional, então os novatos não precisam aprender no primeiro jogo.

Eu apenas sinto que pode haver uma possível desconexão entre os desenvolvedores de jogos reais e os contribuidores.

Esta é uma comunidade aberta. Os desenvolvedores de jogos são convidados a vir e expressar sua opinião, assim como você fez. De qualquer forma, muito tempo vai passar antes que as anotações se tornem realidade.

[...] só temo que gds se distancie cada vez mais de sua simplicidade, só isso. já é mais do que suficiente ...

Se já fosse bom o suficiente, não receberíamos solicitações de recursos para ele.

além disso, ter 3 linhas para uma palavra-chave de exportação é muito complicado, em comparação com apenas especificar tudo em uma linha. por exemplo: onready var my_sprite = $ Sprite é muito mais limpo

A sintaxe ainda não foi finalizada. É bem provável que ele não substitua onready e export palavras-chave imediatamente.

Eu realmente gosto da ideia, muito parecido com atributos em C #.

As anotações de aulas e sinais também podem ser interessantes.

Os plug-ins do inspetor que entram em ação automaticamente, independentemente de uma propriedade, método ou classe ter uma anotação personalizada específica, seriam muito fáceis.
Quanto à sintaxe, prefiro algo que também possa ser opcionalmente escrito em uma única linha, mas não é tão importante.

Como poderia ser o processo de definição de anotações personalizadas? Eu preferiria que eles não fossem definidos livremente todas as vezes no código, mas que fossem criados pelo usuário com uma definição unívoca, assim como as classes.

Eu acho que isso precisa ser mais investigado, eu acho que seria ótimo adicionar à linguagem (como sintaxe opcional etc. etc) para não confundir novatos completos tentando entrar.

Acho que a seguinte sintaxe pode ser boa para olhar:

<strong i="7">@export</strong> type=String, hint=MULTILINE

adicionar a vírgula entre os "parâmetros", acho que tornaria um pouco mais consistente com a sintaxe atual, como:

export (String, MULTILINE) var my_var

a primeira versão é um pouco mais prolixa, mas acho que também a torna mais explícita e com o preenchimento automático não deve doer muito :)

Mais discussões de sintaxe devem acontecer no futuro. No geral, gosto da ideia.

As anotações são uma boa forma de injeção de configuração. Mas separar a configuração e o código pode ser uma abordagem mais limpa da IMO. Pode ser mais útil adicioná-los como arquivos de cabeçalho.

Do comentário de @bojidar-bg ...

De qualquer forma, muito tempo vai passar antes que as anotações se tornem realidade.

Alguém pode explicar qual é o problema de "bloqueio" que atrasaria essa implementação? É apenas familiaridade com GDScript / mão de obra ou há recursos específicos que precisam ser implementados com antecedência para oferecer suporte a anotações?

Bem, já se passou bastante tempo desde o meu comentário, então acho que isso já prova isso?

O principal bloqueador para suporte de anotação seria conseguir que os desenvolvedores principais concordassem sobre a sintaxe e a semântica. Posteriormente, a implementação deve ser relativamente fácil.

Precisamos discutir isso com @reduz, já que ele prefere que as anotações sejam apenas para metadados, elas não devem afetar o script ou o comportamento do editor. Isso tornaria minha proposta original totalmente inútil.

Ainda acho que as anotações são claras o suficiente, especialmente ao substituir palavras-chave únicas ( onready , master , puppet , etc.). Mas ainda precisamos chegar a um consenso.

Acho que seria uma adição fantástica ao GDScript conforme descrito. Não acho que deva ser limitado a metadados, ele definitivamente deve ultrapassar muitas das palavras-chave que são usadas para variáveis, especialmente export que pode ser um pouco difícil de ler em alguns casos; dividi-lo em várias declarações ajuda na compreensão, eu acho.

Também pode ser usado para resolver aquele problema de 3 anos # 6204 de uma forma elegante:

<strong i="8">@export</strong>
<strong i="9">@export_tooltip</strong> "The name used when displaying this item in the inventory and in shops."
var display_name := ""

Também concordo que eles devem suportar mais do que apenas metadados. Isso simplificaria muita lógica e melhoraria a legibilidade imo.

Eu concordo com @willnationsdev e adoraria conectar sinais por código usando anotações, algo assim pode realmente melhorar a legibilidade do código:

@connect("timeout")
func _on_Timer_timeout():
   ...

@rluders assumindo que o script está em um nó Timer , talvez.

@Zylann, é claro. Apenas um exemplo simples. Ele pode suportar os parâmetros "alvo" e omiti-los para a auto-conexão. Por exemplo, se o script estiver sendo executado fora de Timer :

@connect("timeout", $Timer)
func _on_Timer_timeout():
  ...

Não tenho ideia de como isso poderia ser implementado, mas adoraria ver anotações em gds, especialmente para palavras-chave. E, para registro, eu preferiria que '()' fosse usado em vez de ponto-e-vírgula ou novas linhas para separar anotações.

Seria ainda melhor se pudéssemos criar nossas próprias anotações + processadores de anotação completos.

@Zylann, é claro. Apenas um exemplo simples. Ele pode suportar os parâmetros "alvo" e omiti-los para a auto-conexão. Por exemplo, se o script estiver sendo executado fora de Timer :

@connect("timeout", $Timer)
func _on_Timer_timeout():
  ...

Isso poderia ser suportado por um plugin de alguma forma, eu não faria dele um recurso central.
Os plug-ins podem se tornar ainda mais poderosos.

tudo o que posso dizer é que estou feliz por ter aprendido o gdscript antes que essas coisas fossem implementadas, porque

@export_hint(ENUM)
@export_hint_string("Attack,Defense")
export var my_enum : int = 0

teria sido muito assustador e difícil de analisar para mim, como um iniciante

@sleepcircle Tentaremos manter o GDScript simples em todos os casos. Portanto, não precisa ser sarcástico aqui: o código que você citou era apenas uma proposta, não _a_ sintaxe futura.

Sinto muito, não estava tentando ser sarcástico. Eu estava apenas presumindo, uma vez que a maioria parecia aprovar esses acréscimos, que eles eram inevitáveis.

Só queria gastar meus $ 0,02 como instrutor de desenvolvimento de jogos. Aviso: Comentário desnecessariamente longo que não contribui muito, apenas minha experiência de ensino de programação por 5 anos sobre como os novos desenvolvedores perceberão isso.

Acho que é importante, ao criar novos idiomas, como anotações, que você deva pegar carona em todas as possibilidades. Por exemplo, com connect , agora funciona bem, pois faz sentido para um novo desenvolvedor que você chame uma função que receba parâmetros e tenha alguns efeitos colaterais.

Se @ foi usado exclusivamente para metadados, então sempre que um novo desenvolvedor vir um @ ele o reconhecerá como metadados que não afetam sua lógica de código. Se afetasse a lógica, é importante que não adicionemos novos idiomas que às vezes são usados ​​como x e às vezes como y .

No momento, para modificar uma variável, existem prefixos, sufixos e alternativas de var. Há algumas coisas que vou listar que não são necessariamente "modificadores de variável", mas novos desenvolvedores podem vê-los desta forma

  • Prefixos: onready , export(...)

    • Cada um deles tem um tipo diferente de comportamento. onready afeta o carregamento da variável de tempo de execução, export é uma espécie de dica / metadados do editor. Tê-los usados ​​no mesmo lugar parece que seu comportamento deve estar conectado de alguma forma, quando na verdade não é

  • Alternativas: class_name , extends , signal , enum , const , func

    • Esses formatos alternativos parecem bem, mas diferenciar um "enum" e "const" de, digamos, ints ou strings parece uma escolha estranha

  • Sufixos: setget

    • Setget em sua própria categoria está certo, mas é semelhante a export por ser mais uma palavra-chave açucarada para desenvolvedores e não tanto uma mudança lógica. Eu posso ver pessoas com opiniões diferentes aqui, embora

  • Em algum lugar no meio: digitando var x : int = 5

    • Essa digitação intermediária parece estranha, especialmente quando "enum" e "const" são palavras-chave alternativas para var para representar a mesma coisa. Definitivamente, um argumento de que const é semelhante a setget no sentido de que modifica a experiência do desenvolvedor mais do que uma ferramenta para a própria lógica do jogo.

Portanto, agora vamos examinar a adição de anotações.

As anotações seriam um conceito / idioma totalmente novo que precisaria ser ensinado a novos desenvolvedores. Idealmente, os novos desenvolvedores devem ser capazes de se atualizar e fazer as coisas conhecendo o mínimo de idiomas possível, para que possam escolher organicamente novos idiomas à medida que se tornem úteis para eles. Pense nisso como uma árvore tecnológica.

  • (Camada 1) Eles podem fazer um jogo conhecendo apenas func, var e alguns conceitos básicos de programação, como chamadas de função, condicionais e loops
  • (Camada 2) Em seguida, eles passam a aprender açúcar / funcionalidade úteis, como sinais, const, enum
  • (Camada 3) Eles aprendem atalhos, como setget, onready
  • (Camada 3.1) Eles aprendem açúcar somente para desenvolvedores, que não mudará seu jogo, mas mudará seu processo , com coisas como exportações, descrições do editor, ferramentas e digitação
  • (Nível 4) Puramente documentação e estrutura do projeto

Acho que os níveis 3-4 são os principais alvos para anotações. Existem dois argumentos de venda que eu daria aos meus alunos para as duas implementações diferentes:

  • Puramente metadados: "Para ajudar com sua documentação e colaboração, aprenda sobre anotações para adicionar alguns metadados a seus scripts. Eles são mais poderosos do que apenas usar comentários."
  • Dev shorthands / sugar: "Se você está procurando reduzir seu código ou torná-lo mais legível, dê uma olhada nas anotações. Elas permitem que você descreva variáveis ​​e funções enquanto fornecem algumas ferramentas de editor e atalhos."

Eu ensinei vários devs Godot, e acho que fazendo anotações pelo menos uma opção de Nível 3 e no máximo Nível 4. Prefiro não ter que mostrar a eles um símbolo @ até que eles já estejam criando jogos inteiros e razoavelmente complexos e procurando melhorar seu processo .

Isso significa que minha opinião cai sobre nós usando anotações exclusivamente para abreviações de desenvolvimento que não são importantes para a funcionalidade do jogo / têm implementações alternativas ou puramente para documentação, já que é fácil dizer às pessoas "aprenda anotações uma vez que você está construindo projetos maiores que precisam de documentação".

Pontos específicos do tópico:

  • Eles devem ser adequados para as exportações, já que as exportações não são críticas para nenhum jogo
  • Onready é um atalho útil no início, mas não é necessário, pois novos desenvolvedores podem começar iniciando em _ready e a perspectiva de anotações aninhadas significa escrever onready bem menos vezes
  • setget já tem uma sintaxe tão estranha, e já tem seu próprio idioma como o único sufixo, que poderia estar totalmente lá
  • Conectar: ​​Como eu começo com, já está perfeito com o idioma de chamada de função. Ter várias maneiras de se conectar pode confundir o espaço do código do tutorial / amostra. Talvez permitir que as pessoas escrevam suas próprias anotações seja melhor do que padronizar isso, para que os desenvolvedores que trabalham em projetos fechados possam construir uma biblioteca de anotações que não necessariamente confluem com o espaço público
  • Tipos: os tipos estão em uma situação estranha agora, onde alguns modificadores de tipo são alternativas e alguns modificadores de tipo estão no meio. Talvez tê-los como anotações funcione: @type(const int) @type(enum) , o que unificaria todos eles como um açúcar orientado para o desenvolvedor

Mais uma vez, não é uma grande contribuição, mas vale a pena pensar ao pensar sobre qual funcionalidade deve ser incluída nas anotações. Acho que são uma ótima ideia, mas não sei exatamente onde se encaixam. Desculpe pela extensão, sou sempre um pouco prolixo.

Eu não gosto disso.
Não quero ter um monte de anotações para cada campo, propriedade e método

Eu prefiro ter mais palavras-chave

se as pessoas não gostarem de muitas palavras-chave, podemos remover algumas delas

export MyClass : Node2D # export replaces class_name, : replaces extends 

signal mySignal #signal is kept

group(MyHeader, "res://icon.png" )
export var my_property : Array(int) setget _set_my_property, _get_my_property # : replaces export type

var test = 0 # no need for onready. variables declared outside of _ready automatically try to be onready vars

#others are kept

Eu concordo inteiramente com a proposta original.

Não discordo dos comentários acima, mas os prós superam os contras.

@ Shadowblitz16 Muitas dessas sugestões são confusas para as pessoas aqui, pelos seguintes motivos ...

export MyClass : Node2D # export replaces class_name, : replaces extends

export , class_name , : e extends configuram, cada um, 4 pontos de dados e sistemas completamente separados. Você não pode simplesmente trocá-los sem impactar outras coisas de forma irrecuperável.

  • export configura o objeto PropertyInfo gerado que é enviado ao Inspetor para construir a GUI do editor.
  • class_name registra o script como uma classe global no ScriptServer. Tecnicamente, não tem nada a ver com o sistema de tipos. Faz parte da "tipagem estática" do GDScript apenas na medida em que acontece de criar uma instância global do script em tempo de análise em vez de em tempo de execução.
  • : é usado para dicas de tipo opcional . A menos que você convença as pessoas a fazer GDScript com digitação estática o tempo todo e / ou proponha uma sintaxe de dica de tipo alternativa, não há como redirecionar o token de dois pontos.
  • extends é usado para a classe herdada (como você sabe). Esta é uma sintaxe bastante comum em outras linguagens, e toda a documentação e tutoriais já seguem esse método. Não haverá um grande incentivo para abandonar isso e criar mais trabalho por uma razão puramente cosmética.
group(MyHeader, "res://icon.png")

Não está claro para mim o que isso faria. Quer dizer, parece que o nó será adicionado ao grupo "MyHeader" (o que pode fazer sentido), mas para que serve o ícone? Os grupos não possuem ícones associados a eles.

export var my_property : Array(int) setget _set_my_property, _get_my_property # : replaces export type

Como já foi dito, todas essas coisas afetam sistemas diferentes , não o mesmo sistema. Além disso, pode haver momentos em que você deseja que o tipo de um valor ou sua inicialização seja flexível. Por exemplo, em GDScript dinâmico, você pode fazer algo assim:

onready export(NodePath) var the_node = get_node(the_node)
var test = 0 # no need for onready. variables declared outside of _ready automatically try to be onready vars

Inicializar dados antes da notificação pronta não faria sentido. Os scripts são associados à classe Object, não à classe Node. As propriedades do script são inicializadas durante a construção. Isso não muda mesmo quando você chega ao construtor da classe Node. A notificação _ready() acontece muito mais tarde após a instanciação. Ter o tempo padrão de inicialização da variável diferente entre objetos e nós seria extremamente confuso e levaria a muitos comportamentos imprevisíveis para aqueles que estão aprendendo e usando Godot.


Não pretendo derrubar suas sugestões, mas apenas explicar por que as pessoas não estão vendo a justificativa para essas mudanças sugeridas.

@willnationsdev está tudo bem, eu entendo
que tal fazer anotações e palavras-chave extras
desta forma, os usuários podem usar Anotações se quiserem e Palavras-chave se não quiserem ter dezenas de Anotações por campo

Editar: observe C # como atributos que permitem combiná-los assim ..
[Attribute1(), Attribute2()]
no entanto, embora isso possa ajudar a reduzir a contagem de linhas, ainda é um pouco feio

@ Shadowblitz16 Preferimos ter apenas uma maneira óbvia de fazer as coisas, quando possível. Ter duas sintaxes diferentes seria contrário a esse objetivo.

@Calinou Acho que o gdscript deve ser deixado como está, se as pessoas não conseguirem se comprometer.
1 - quebra a compatibilidade com versões anteriores desnecessariamente
2 - cria arquivos maiores e código menos legível
3 - força as pessoas a mudarem para um novo sistema ao qual não estão acostumadas.
4 - força as pessoas a usarem um sistema que elas podem não querer

1 - quebra a compatibilidade com versões anteriores desnecessariamente
2 - cria arquivos maiores e código menos legível
3 - força as pessoas a mudarem para um novo sistema ao qual não estão acostumadas.
4 - força as pessoas a usarem um sistema que elas podem não querer

Honestamente, esses são argumentos muito ruins. 3 desses 4 pontos são inerentes a quaisquer grandes mudanças em uma API, e o primeiro deles poderia ser contornado mantendo a compatibilidade com o sistema mais antigo baseado em palavras-chave por um tempo (provavelmente com um aviso de descontinuação).

_Editar: também poderíamos fornecer uma ferramenta de conversão automática, eu acho._

Para o ponto 2, embora eu ache que todos concordarão com o fato de que as anotações podem levar a arquivos com mais linhas, a maioria das pessoas aqui discorda sobre o fato de que cria um código menos legível.

@groud, isso está usando anotações para coisas desnecessárias
1 - por que precisamos descontinuar algo que funciona?
2 - é menos legível se você tiver que rolar 5 linhas para baixo para ver um campo

  • exportar é basicamente uma palavra-chave pública para o editor
  • onready é basicamente uma declaração var antes de o script ser executado

ambos não são adequados para serem anotações

as definições de membro são a única coisa para a qual eu realmente posso ver que isso é bom e eles teriam que ser recolhíveis neste caso, eles não são.

@groud, isso está usando anotações para coisas desnecessárias

Muitos casos de uso foram apresentados neste tópico. Seja para documentação, introspecção, plug-ins mais complexos ... há muitos casos de uso para anotações que não podem ser cobertos por palavras-chave.

1 - por que precisamos descontinuar algo que funciona?

Existem muitas razões para fazer algo assim. Qualquer recurso pode precisar evoluir para permitir uma API mais limpa, mais flexibilidade, etc ... E uma vez que uma nova versão seja amplamente utilizada, é melhor remover a compatibilidade com a versão anterior quando possível, pois isso definitivamente tem um custo de manutenção.

2 - é menos legível se você tiver que rolar 5 linhas para baixo para ver um campo

Não há necessidade de exagerar. O objetivo de discutir tal proposta é permitir uma sintaxe inteligente o suficiente para evitar tais problemas. IMHO, as dicas de exportação podem ser integradas como argumentos para as anotações de exportação (desde que possamos ter um sistema de argumentos nomeado, eu acho). Em tais situações, o sistema pode ocupar ainda menos espaço do que antes.

Além disso, também podemos imaginar ter as anotações nas mesmas linhas do campo. Não acho que isso possa causar problemas.

exportar é basicamente uma palavra-chave pública para o editor
onready é basicamente uma declaração var antes de o script ser executado
ambos não são adequados para serem anotações

Bem, provavelmente você tem ideias preconcebidas sobre para que servem as anotações. Eu acho que esses casos de uso se encaixam perfeitamente em um sistema de anotação (e parece que muitas pessoas o fazem). Mas, de fato, acho que cada situação deve ser discutida caso a caso.

Não vejo o argumento das "linhas" particularmente bom. Mesmo se as anotações não permitirem diretamente várias instruções por linha (ou uma forma de "prefixo"), você ainda pode usar ; como um delimitador.

<strong i="7">@onready</strong> var my_sprite = $Sprite
@onready; var my_sprite = $Sprite


@export_hint_string("Attack,Defense")
@export_hint(ENUM) export var my_enum : int = 0

@export_hint_string("Attack,Defense")
@export_hint(ENUM); export var my_enum : int = 0


<strong i="8">@export_hint_string</strong> "Attack,Defense";
<strong i="9">@export_hint</strong> ENUM export var my_enum : int = 0

<strong i="10">@export_hint_string</strong> "Attack,Defense"
<strong i="11">@export_hint</strong> ENUM; export var my_enum : int = 0


<strong i="12">@export</strong> type=String hint=MULTILINE; var my_text = ""

# more options

@export(type = String, hint = MULTILINE) var my_text = ""
@export(type = String, hint = MULTILINE); var my_text = ""

@export(String, hint = MULTILINE) var my_text = ""

# I personally prefer this one (positional and named args supported, default/optional args too)
@export(String, MULTILINE) var my_text = ""
@export(String, hint = MULTILINE) var my_text = ""
@export(type = String, hint = MULTILINE) var my_text = ""
@export(int, ENUM, "Attack,Defense") var my_enum:= 0

Edit: Oh, eu fui muito lento, @groud já abordou o argumento das linhas. Bem, pelo menos aqueles poucos exemplos de código adicionaram algo a este tópico.

essa é a opinião de vocês.
Eu pessoalmente acho o @ feio

EDITAR:
então, como funcionaria a declaração de membro?
fazer isso seria horrível

<strong i="10">@description</strong> "Adds two numbers and returns the result."
<strong i="11">@parameter</strong> name=num1 type=float description="The first number"
<strong i="12">@parameter</strong> name=num2 type=float description="The second number"
<strong i="13">@returns</strong> type=float description="num1 and num2 added together"
func add(num1, num2):
    return num1 + num2

a menos que pudesse ser recolhido do início de @description ao início de func

Acredito que as anotações não se destinam a substituir tipos (como seu exemplo parece fazer). Se você não quiser anotações de documentação, não será forçado a usá-las:

func add(num1: float, num2: float) -> float: return num1 + num2

Essa confusão provavelmente decorre da situação nada ideal com dicas de exportação onde, até onde eu sei, você não pode usar tipos reais (e o problema de não ter tipos genéricos que surpreendentemente exportam suporte de dicas para alguns tipos, como um array).

Eu pessoalmente acho o @ feio
então, como funcionaria a declaração de membro?
fazer isso seria horrível

Em outras línguas, esse propósito geralmente serve para comentários, não para anotações, e geralmente são parecidos ou mais prolixos do que o que foi sugerido. Em uma família de linguagem C (linguagens mais populares) o @ é bastante comum para anotações (por exemplo, Java, JavaScript, TypeScript, Scala e do que li Python também).

TypeScript (acredito que os tipos nos documentos não são necessários e as ferramentas podem usar tipos reais):

/** Adds two numbers and returns the result.
 * <strong i="16">@param</strong> num1 {float} The first number
 * <strong i="17">@param</strong> num2 {float} The second number
 * <strong i="18">@return</strong> {float} num1 and num2 added together
  **/
const add = (num1: number, num2: number): number => num1 + num2;

sabor de função:

@description("Adds two numbers and returns the result.")
@parameter(num1, "The first number", type=float)
@parameter(num2, "The second number", type=float)
@returns("num1 and num2 added together", type=float)
func add(num1: float, num2: float) -> float:
    return num1 + num2

sem tipos duplicados:

@description("Adds two numbers and returns the result.")
@parameter(num1, "The first number")
@parameter(num2, "The second number")
@returns("num1 and num2 added together")
func add(num1: float, num2: float) -> float:
    return num1 + num2

sabor sem parênteses:

<strong i="28">@description</strong> "Adds two numbers and returns the result."
<strong i="29">@parameter</strong> num1 "The first number"
<strong i="30">@parameter</strong> num2 "The second number"
<strong i="31">@returns</strong> "num1 and num2 added together"
func add(num1: float, num2: float) -> float:
    return num1 + num2

Eu gosto mais dessa sintaxe para comentários de documentos. Ainda não estou convencido sobre o uso de anotações para fins de documentação, já que para anotações não doc, eu prefiro sintaxe semelhante a funções.

Usei nomes de anotação do exemplo anterior, @parameter poderia ser simplesmente @param como em outros idiomas, @description poderia ser @desc , @descr ou @func .

No GodoDoc estou usando sintaxe baseada em TypeScript (TypeDoc que por si só é baseado em JSDoc e Javadoc) e, na minha opinião, parece funcionar muito bem:

## Same as [[bool_]], but `on_false`/`on_true` are functions.
## Only selected function will be called and its return value will be returned from `bool_lazy`.
## <strong i="44">@typeparam</strong> T {any} Return type
## <strong i="45">@param</strong> cond {bool} Condition
## <strong i="46">@param</strong> on_false {FuncLike<T>} Function to call and return its result when `cond` is `false`
## <strong i="47">@param</strong> on_true {FuncLike<T>} Function to call and return its result when `cond` is `true`
## <strong i="48">@return</strong> {T}
func bool_lazy_(cond: bool, on_false, on_true): return GGI.bool_lazy_(cond, on_false, on_true)
var bool_lazy = funcref(self, "bool_lazy_")

a menos que pudesse ser recolhido do início de @description para o início de func

Sim, geralmente dobrar e uma opção para dobrar padrão seria uma boa adição ao editor (dobrar com base em um tipo de bloco, por exemplo, você pode habilitar nas configurações que as classes internas sejam recolhidas por padrão).

Gosto da possibilidade de colocar uma anotação na frente ou acima, para isso o @annotation(a, b) é bom, com colchetes opcionais se nenhum parâmetro for fornecido. Ser capaz de colocar na frente permite a mesma velocidade de escrita da palavra-chave de hoje, dado que export e onready são muito comuns com propriedades.

No entanto, em termos de uso, também não gosto de documentação. Estou acostumado a anotações que afetam o programa (mesmo que indiretas), enquanto a documentação frequentemente triplicaria sua quantidade para uso semelhante a comentários, apareceria em todos os lugares e destacaria o mesmo que as anotações funcionais ... não serve para algo tão onipresente. Basicamente, gosto do mesmo uso de anotações que pode ser encontrado em C #, o que leva a muito menos anotações tendo que ser escritas na parte superior dos membros (geralmente são muito raros, nem todo mundo precisa escrever 5 linhas como alguns exemplos mostram) . Se o argumento for sobre Godot não ter API para especificar documentos de script, então esse é o problema, não deve ser resolvido apenas com anotações IMO. Pelo menos, acho que se poderia usar isso opcionalmente, mas não gostaria de ser forçado a fazer dessa forma, o que considero inconveniente para documentação em escala real. (além disso, os scripts não são apenas GDScript, e o caso extremo de usar _get_property_list torna isso ainda mais estranho)

Acho que concordo totalmente com você Zylann. Eu pessoalmente permitiria essa sintaxe para exportação (ou já) como palavras-chave:

# No parenthesis when there are no parameters
<strong i="6">@export</strong> var myvar
# With parenthesis for parameters
@export(ENUM, "Up,Down,Left,Right") var myvar2
# Being able to write the annoation on the line before
@export(ENUM, "Up,Down,Left,Right") 
var myvar2

Em relação à parte da documentação, eu simplificaria ainda mais a sintaxe (tomando o exemplo de @mnn ):

<strong i="11">@description</strong> "Adds two numbers and returns the result."
<strong i="12">@parameter</strong> "The first number" # No need to name the args if they are ordered
<strong i="13">@parameter</strong> "The second number"
<strong i="14">@returns</strong> "num1 and num2 added together"
func add(num1: float, num2: float) -> float:
    return num1 + num2

No entanto, concordo que é obrigatório desenvolver outro sistema para que a documentação possa ser escrita em outro lugar. Em um json, XML ou primeiro arquivo, eu diria. A documentação no código não se encaixa em todos os projetos, e eu concordo que adicionar muitas anotações apenas para a documentação pode ser irritante e pode tornar o código mais difícil de ler em alguns casos.

Vinculando para relevância: godotengine / godot-propostas # 177

Bem tarde para a festa, mas como dev que depende fortemente de metadados e reflexão para desenvolver plug-ins, eu realmente adoraria ver as anotações se tornando uma coisa em godot.

Embora eu ache que isso torna algumas coisas mais bonitas (como a exportação e outras coisas já existentes), meu principal argumento seria para plug-ins personalizados que podem utilizar anotações em sua extensão máxima.

Com relação à palavra-chave onready e suas limitações.

Eu acho que é seguro dizer que a maioria das pessoas usa onready para inicializar referências de nó desde o início. Exceto que pode não ser viável sem problemas a longo prazo, porque quando você exemplifica algumas cenas que são dependentes de _ready , você pode topar com o problema de referenciar null :

func explode():
    var bomb = preload("res://explosion.tscn").instance()
    # Oops, forgot to `add_child(bomb)` earlier
    bomb.fuse.wait_time = 5.0 # ERROR: fuse is `null`
    add_child(bomb)
    # ... because `fuse` is a $Timer node 
    # which is only initialized once added to the scene tree.

Claro que você precisa add_child() a cena instanciada antes de tentar definir o fuse , mas e se outros nós / objetos precisarem estar cientes do fusível exato antes que a cena seja adicionada à árvore de cena ?

Depois de algum tempo, encontrei uma solução conforme descrito em https://github.com/godotengine/godot/issues/33620#issuecomment -559999681. Como você pode notar lá, onready é apenas NOTIFICATION_READY , enquanto o que eu realmente precisava era NOTIFICATION_INSTANCED e inicializar minhas referências ainda mais cedo. O único problema é que não há oninstanced palavra-chave, e acho que você pode descobrir a que estou levando. 🙂

Então, eu acho que seria bom refazer a palavra-chave onready como uma anotação, ao mesmo tempo que oferece suporte a alguns outros casos (como o meu, como sempre!) Com a funcionalidade @oninstanced sem inchar a linguagem de script , bem como adicionar suporte para outras notificações relativas à inicialização ( _init , _enter_tree , etc).

Proposta relacionada: godotengine / godot-propostas # 260.

Abriu uma proposta com detalhes mais específicos: https://github.com/godotengine/godot-proposals/issues/828

Substituído pela proposta acima.

Esta página foi útil?
0 / 5 - 0 avaliações