Ich versuche, einen Code-Analysator zu implementieren, der eine andere Java-Datei als Eingabe verwendet. Für jede Variablendeklaration möchte ich prüfen, ob der Typ, zu dem die Variable gehört, generisch ist oder nicht. Gibt es eine einfache Möglichkeit, das zu tun?
Zum Beispiel möchte ich dafür:
%Vor%Ich kann möglicherweise eine Registrierung erstellen, die alle generischen Typen enthält, aber das Problem damit wäre, wenn ich einen benutzerdefinierten generischen Typ implementiere, dann müsste ich die Registrierung jedes Mal aktualisieren. Gibt es dafür eine einfache Lösung?
Auch wenn HashSet
generisch sein kann, ist der Typ HashSet
selbst (ohne <T>
) ein roher Typ . Daher würde ich mit dem Ansatz gehen, den tatsächlichen Typ der deklarierten Variablen zu scannen, vielleicht eine Regex auf den Typ anzuwenden, um zu sehen, ob die spitzen Klammern existieren:
Wenn Sie einen gültigen Bezeichner strikt berücksichtigen möchten, können Sie dessen Definition im Java-Sprachspezifikation :
Bezeichner:
IdentifierChars, aber kein Schlüsselwort oder BooleanLiteral oder NullLiteral
IdentifierChars:
JavaLetter {JavaLetterOrDigit}
JavaLetter:
jedes Unicode-Zeichen, das ein "Java-Buchstabe" ist
JavaLetterOrDigit:
jedes Unicode-Zeichen, das ein "Java Buchstabe oder Ziffer" ist
Ein "Java-Buchstabe" ist ein Zeichen, für das die Methode
Character.isJavaIdentifierStart(int)
true zurückgibt.Ein "Java letter or digit" ist ein Zeichen, für das die Methode
Character.isJavaIdentifierPart(int)
true zurückgibt.
Dies wird nach Objekt, Klasse oder Klassennamen getestet.
Update: Mehrere Überarbeitungen dieses Codes auf Basis hilfreicher Kommentare haben einige interessante Testfälle ergeben. Letztendlich hängt jedoch eine angemessene Lösung des Problems davon ab, wie genau die Frage definiert ist. Beziehen Sie sich auf frühere Überarbeitungen und Kommentare.
%Vor%Die Ergebnisse der Ausführung des obigen Codes:
%Vor%Die anderen Antworten scheinen sich auf die Verwendung eines regulären Ausdrucks oder einer regulären Reflexion zu konzentrieren, aber dies scheint ein Parser zu sein. Das ist es, was ich dir empfehle.
Als Beispiel hat Eclipse sein JDT-Plug-in (Java Development Tools), das Ihnen alle Analyse-Tools zur Verfügung stellt, die Sie für dieses Recht benötigen. Alles, was Sie tun müssen, ist die JDT bitten, Ihnen einen Abstract Syntax Tree (AST) mit aktivierten Bindungen zu geben. Wenn eine Variable deklariert wird, erhalten Sie eine ITypeBinding für den deklarierten Typ der Variablen und eine weitere für den instanziierten Typ (wenn die Variable in der Deklaration instanziiert wird).
Und ITypeBinding hat Methoden, die Ihnen sagen, ob es generische, parametrisierte, etc.
istSie erhalten auch die Typparameter, falls Sie diese benötigen.
Es gibt noch andere Java-Parser-Optionen, aber das ist die, mit der ich vertraut bin.
==============================================
Spezifische Ergebnisse mit dem Eclipse JDT
Fall 1: HashSet<String> h1 = new HashSet();
Fall 2: HashSet<String> h2 = new HashSet<>();
Fall 3: HashSet<String> h3 = new HashSet<String>();
Ziel dieser Übung ist es, wie bisher verstanden, Fall 1 als nicht generisch (roh) und Fälle 2 und 3 als generisch (sie haben Typparameter, obwohl in Fall 2 der Typparameter impliziert ist) zu erkennen.
Betrachte nur die Knoten, die aus new HashSet...
Alle drei Fälle erzeugen eine ClassInstanceCreation-Instanz.
Fall 1 und Fall 2 haben Argumente vom Typ 0, während Fall 3 ein Argument vom Typ hat.
Die ITypeBinding für Fall 1 ist als roh gekennzeichnet, während für die Fälle 2 und 3 sie als parametrisiert markiert sind. Dies ist ein Erfolg , da wir zwischen Fall 1 einerseits und den Fällen 2 und 3 andererseits unterscheiden können.
Die ITypeBinding für Fall 1 hat 0 Typargumente, während Fall 2 und 3 beide 1 Typargument in der ITypeBinding haben. Beachten Sie, dass Fall 2 im AST selbst 0-Typ-Argumente hat, aber die Bindung ein Argument vom Typ hat. Dies erlaubt es, zwischen einem expliziten Typargument und der Verwendung des Diamantoperators zu unterscheiden.
Alle für die Ausführung dieser Aufgabe erforderlichen Informationen sind im AST und in den Bindungen verfügbar.
Hier sind die schlechten Nachrichten: Die Bindungen sind nur verfügbar, wenn der Byte-Code verfügbar ist, d. h. dies ist keine einfache Textanalyse.