Pular para o conteúdo principal

DevNotes #1 - Identificadores entre aspas

· Leitura de 2 minutos
Maintainer

Alguns dias atrás, descobri que o ZPA não estava tratando corretamente os identificadores entre aspas. Especificamente, o componente responsável pela criação da tabela de símbolos não estava identificando e contando corretamente os usos de identificadores entre aspas. Isso levava a resultados imprecisos, que poderiam afetar a qualidade da análise de código.

No Oracle SQL, "quoted user-defined identifiers" são identificadores que estão entre aspas duplas. Identificadores entre aspas são case-sensitive, o que significa que "My Table" e "my table" são considerados identificadores diferentes. É diferente dos outros identificadores sem aspas, que são case-insensitive (onde letras maiúsculas e minúsculas não importam).

No entanto, há um detalhe: se um identificador entre aspas, sem suas aspas duplas, for um identificador de usuário comum válido (começa com uma letra e contém apenas letras, dígitos, $, # e _) e estiver em letras maiúsculas, então ele é tratado como um identificador não entre aspas. A definição parece longa, mas, na prática, isso significa que MY_TABLE, my_table e "MY_TABLE" são considerados o mesmo identificador.

Portanto, vamos considerar o seguinte exemplo:

DECLARE
"HELLO" VARCHAR2(15) := 'UPPERCASE';
"Hello" VARCHAR2(15) := 'Initial Capital';
"hello" VARCHAR2(15) := 'lowercase';
BEGIN
DBMS_OUTPUT.PUT_LINE("HELLO");
DBMS_OUTPUT.PUT_LINE("Hello");
DBMS_OUTPUT.PUT_LINE("hello");
DBMS_OUTPUT.PUT_LINE(hello);
END;

Neste exemplo, temos três variáveis declaradas com identificadores entre aspas: "HELLO", "Hello" e "hello". Todas as três são consideradas identificadores diferentes porque têm diferentes capitalizações.

A última linha com DBMS_OUTPUT.PUT_LINE(hello); é interessante porque o identificador está sem aspas. Este hello está se referindo à variável declarada com o identificador entre aspas "HELLO". Como o identificador entre aspas "HELLO" se encaixa na situação descrita anteriormente, ele é tratado como se não tivesse aspas e é case-insensitive.

Enquanto eu trabalhava no ZPA, notei que na tabela de símbolos esse tipo de identificador não estava tratado corretamente e causava falsos positivos nas regras UnusedVariable, UnusedCursor, UnusedParameter e VariableHiding.

Testando este trecho de código com o ZPA Toolkit 3.5.1, podemos ver que as três variáveis declaradas com identificadores entre aspas estão sendo relatadas incorretamente como usos de "HELLO" e a última referência não entre aspas nem mesmo é considerada.

ZPA 3.5.1 - Antes

Após as correções, o ZPA passou a considerar corretamente todas as situações:

ZPA next - Depois