Анализ на изходния код с помощта на Java 6 API

от Сиема Ричард, Дийпа Собхана

Замисляли ли сте се някога как инструменти като Checkstyle или FindBugs извършват статичен анализ на кода или как интегрираните среди за разработка (IDE) като NetBeans или Eclipse изпълняват бързи корекции на код или намират точните препратки към поле, декларирано във вашия код? В много случаи IDE имат свои собствени API за анализиране на изходния код и генериране на стандартна дървовидна структура, наречена абстрактно синтаксисно дърво (AST) или „парсинг дърво“, която може да се използва за по-задълбочен анализ на изходните елементи. Добрата новина е, че вече е възможно да се изпълнят споменатите задачи плюс много повече с помощта на три нови API, въведени в Java като част от изданието на Java Standard Edition 6. Приложните програмни интерфейси (API), които биха могли да представляват интерес за разработчиците на Java приложения, които трябва да извършат анализ на изходния код, са API на Java Compiler (JSR 199),API за обработка на анотации с възможност за свързване (JSR 269) и API на дървото на компилатора.

В тази статия ние изследваме характеристиките на всеки от тези API и продължаваме да разработваме просто демонстрационно приложение, което проверява определени правила за кодиране на Java за набор от файлове с изходен код, предоставени като вход. Тази програма също така показва съобщенията за нарушение на кодирането, както и местоположението на нарушения изходен код като изход. Помислете за прост Java клас, който заменя метода equals () на клас Object. Правилото за кодиране, което трябва да бъде проверено, е, че всеки клас, който реализира метода equals (), трябва също да замени метода hashcode () с правилния подпис. Можете да видите, че класът TestClass по-долу не дефинира метода hashcode (), въпреки че има метода equals ().

public class TestClass implements Serializable { int num; @Override public boolean equals(Object obj)  } 

Нека продължим и анализираме този клас като част от процеса на изграждане с помощта на тези три API.

Извикване на компилатора от код: API на компилатора Java

Всички ние използваме инструмента от javacкомандния ред за компилиране на Java изходни файлове в класови файлове. Тогава защо ни е необходим API за компилиране на Java файлове? Е, отговорът е съвсем прост: както името описва, този нов стандартен API ни позволява да извикаме компилатора от нашите собствени Java приложения; т.е. можете програмно да взаимодействате със компилатора и по този начин да направите компилацията част от услуги на ниво приложение. Някои типични приложения на този API са изброени по-долу.

  • API на компилатора помага на сървърите на приложения да сведат до минимум времето, необходимо за разполагане на приложения, например, като избягва режийните разходи за използване на външен компилатор за компилиране на сървлетни източници, генерирани от JSP страниците.

  • Инструменти за разработчици като IDE и анализатори на код могат да извикат компилатора от редактора или да създадат инструменти, които значително намаляват времето за компилиране.

Класовете на Java компилатор са пакетирани под javax.toolsпакета. В ToolProviderкласа на този пакет се отнася до метод, наречен getSystemJavaCompiler()която връща инстанция на някои клас, който реализира JavaCompilerинтерфейса. Този екземпляр на компилатора може да се използва за създаване на задача за компилация, която ще изпълни действителната компилация. Изходните файлове на Java, които ще бъдат компилирани, ще бъдат предадени на задачата за компилиране. За това API на компилатора осигурява абстракция на файлов мениджър JavaFileManager, която позволява извличане на Java файлове от различни източници, като файлова система, бази данни, памет и т.н. В тази извадка използваме StandardFileManagerфайлов мениджър, базиран на java.io.File. Стандартният файлов мениджър може да бъде придобит чрез извикване на getStandardFileManager()метода наJavaCompilerинстанция. Кодовият фрагмент за гореспоменатите стъпки е показан по-долу:

//Get an instance of java compiler JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); //Get a new instance of the standard file manager implementation StandardJavaFileManager fileManager = compiler. getStandardFileManager(null, null, null); // Get the list of java file objects, in this case we have only // one file, TestClass.java Iterable compilationUnits1 = fileManager.getJavaFileObjectsFromFiles("TestClass.java"); 

Диагностичният слушател може да бъде предаден по избор на getStandardFileManager()метода, за да изготви диагностични доклади за всички нефатални проблеми. В този кодов фрагмент предаваме nullстойности, тъй като не събираме диагностиката от инструмента. За подробности относно другите параметри, предадени на тези методи, вижте API 6 на Java. В getJavaFileObjectsfromFiles()метода на StandardJavaFileManagerвъзвръщаемост на всички JavaFileObjectинстанции, които отговарят на предоставените файлове Java код.

Прочетете останалата част от тази статия

Тази история, „Анализ на изходния код с помощта на Java 6 API“, първоначално е публикувана от JavaWorld.