Ve třetí části seriálu o projektu Eclipse si řekneme, jakým způsobem lze v tomto integrovaném vývojovém prostředí provádět větší zásahy ve vytvářených či editovaných zdrojových kódech. Nejprve se budeme zabývat problematikou poloautomatických oprav chyb ve zdrojových kódech (což je téma, kterým jsme se již začali zabývat minule) a posléze si ukážeme, jak může Eclipse vygenerovat poměrně velké části zdrojových kódů zcela automaticky či jen s malým přispěním programátora. Například se jedná o vygenerování takzvaných getterů a setterů či o refaktoring spočívající kupříkladu v možnosti přenosu vybraných příkazů do samostatné metody, samozřejmě s automatickým zjištěním potřebných parametrů metody i její návratové hodnoty.

Zobrazení chyb v integrovaném vývojovém prostředí Eclipse

V závěrečné kapitole předchozí části seriálu o integrovaném vývojovém prostředí Eclipse jsme si řekli, že Eclipse dokáže ve zdrojových kódech napsaných v Javě automaticky zjišťovat některé typy chyb a taktéž tyto chyby v rámci možností opravovat. Dnes se touto problematikou budeme zabývat detailněji. Na prvním obrázku je zobrazen projekt v Javě, který byl vytvořený a otevřený v integrovaném vývojovém prostředí Eclipse. Projekt obsahuje pouze jedinou třídu nazvanou TestClass se statickou metodou main(). V této metodě je zapsán pouze jediný příkaz: volání metody System.out.printl(). Tato metoda však ve skutečnosti neexistuje, na což vývojové prostředí Eclipse programátora upozorňuje, a to hned několika způsoby (připomeňme si, že některé upozornění se zobrazí až ve chvíli, kdy je zdrojový text uložen pomocí klávesové zkratky Ctrl+S):

  1. Chybně zapsaný příkaz (volání neexistující metody, použití objektu z balíčku, který není importován atd.) je podtržen červenou vlnovkou přímo v okně editoru zdrojových kódů. Pokud se textový kurzor nachází na chybném příkazu, lze použít klávesovou zkratku Ctrl+1 pro výběr takzvané rychlé opravy („Quick Fix“). Význam této klávesové zkratky si vysvětlíme v následujících kapitolách.
  2. Na pravé straně editoru v prostoru napravo od scrollovací lišty je zobrazen červený obdélníček, na který lze najet kurzorem myši. V tomto případě se v místě kurzoru myši zobrazí, o jakou chybu se jedná. Popř. je alternativně možné na červený obdélníček kliknout levým tlačítkem myši; v tomto případě se textový kurzor přesune na vybraný chybný příkaz (výhodné ve chvíli, kdy je v jednom zdrojovém textu více chyb).
  3. V okně „Problems“ zobrazeném ve spodní části Eclipse se pro každou chybu či varování vytvoří nový informační řádek obsahující chybové hlášení, soubor, v němž se chyba nachází, a taktéž číslo řádku. V případě, že je tento řádek aktivní, lze pro něj použít klávesovou zkratku Ctrl+1 pro vyvolání funkce „Quick Fix“ (viz též další kapitolu).
  4. Vývojové prostředí Eclipse na chybu upozorní taktéž zobrazením červeného křížku na levé straně okna editoru. Podobný červený křížek se zobrazí i v „oušku“ (tabu) v horní části okna editoru, a aby toho nebylo málo, je podobný křížek zobrazen i v oknech „Package Exploreru“ a „Outline“.

Z předchozího textu je zřejmé, že integrované vývojové prostředí Eclipse dokáže upozornit na prakticky jakoukoli chybu ve vytvářeném projektu, a to hned několika způsoby. Na globální úrovni, zejména u projektů sestavených z desítek či dokonce stovek tříd a rozhraní, se jedná především o upozornění na chybu pomocí červeného křížku zobrazeného v okně „Package Exploreru“ a taktéž v okně „Problems“ (takto se chyba zobrazí i tehdy, pokud programátor nemá zobrazen zdrojový kód třídy obsahující chybu) a na úrovni lokální pak o upozornění na chyby přímo v editoru zdrojového kódu.

Obrázek 1: Javovský projekt vytvořený a otevřený v integrovaném vývojovém prostředí Eclipse, v jehož jediné třídě je chyba – volání neexistující metody System.out.printl(). Na tuto chybu dokáže Eclipse programátora upozornit, a to několika různými způsoby.

Poloautomatická oprava chyb ve zdrojových kódech

Vývojové prostředí Eclipse, přesněji řečeno jeho modul JDT, obsahuje nejenom funkce pro detekci chyb, ale i funkce pro jejich poloautomatickou opravu. Nejdříve si připomeňme, jakým způsobem lze opravit jednoduchý překlep v názvu třídy nebo metody. Nejjednodušší způsob opravy tohoto typu chyb spočívá ve stlačení klávesové zkratky Ctrl+1 na řádku, v němž byla chyba nalezena a označena vývojovým prostředím. Eclipse zobrazí nabídku možných oprav, kde se většinou nachází i seznam existujících metod či atributů, jejichž název se podobá jménu metody/atributu uvedeného ve zdrojovém textu. V dolní části dočasného okna s nabídkou oprav se taktéž nachází návrh nové podoby (opraveného) zdrojového textu – viz též snímek obrazovky na obrázku číslo 2.

Obrázek 2: Po stisku klávesové zkratky Ctrl+1 na řádku s chybou se zobrazí nabídka oprav, které dokáže Eclipse automaticky provést.

Alternativně je možné použít klávesovou zkratku Ctrl+1 i v okně „Problems“, které se implicitně zobrazuje ve spodní části Eclipse (ovšem za předpokladu, že je zvolena perspektiva „Java“). Ve chvíli, kdy je klávesová zkratka Ctrl+1 použita v okně „Problems“, zobrazí Eclipse poněkud odlišný dialog než v předešlém případě, ve skutečnosti se však i přes jiný způsob zobrazení použijí stejné nabídky oprav. Zmíněný dialog je zobrazen na třetím obrázku.

Obrázek 3: Po stisku klávesové zkratky Ctrl+1 v okně „Problems“ na řádku s nalezenou chybou se zobrazí toto nové okno, v němž lze zvolit způsob opravy chyby.

Poloautomatické doplnění chybějících importů balíčků či tříd

Podívejme se nyní na další typ oprav, který integrované vývojové prostředí Eclipse vývojářům nabízí. Jedná se o poloautomatické doplňování chybějících importů balíčků či tříd. Tuto funkci si opět ukážeme na jednoduchém ukázkovém příkladu, jenž je zobrazen na čtvrtém obrázku. Z tohoto obrázku je patrné, že v projektu jsou dvě chyby způsobené chybějícími importy tříd List a ArrayList (mimochodem si taktéž povšimněte, že Eclipse nemá žádné problémy se zpracováním většího množství chyb vyskytujících se na stejném programovém řádku):

Obrázek 4: Javovský projekt se zdrojovým kódem, který obsahuje dvě chyby způsobené chybějícími importy.

Na obrázku číslo 5 je dialog zobrazený ve chvíli, kdy je klávesová zkratka Ctrl+1 stisknuta v okně „Problems“ u chyby „ArrayList cannot be resolved to a type“. Eclipse pro tento případ nabízí buď import třídy java.util.ArrayList, což je pro tento případ korektní řešení. Druhá možnost spočívá ve vytvoření nové třídy pojmenované ArrayList a možnosti další pak v přejmenování identifikátoru (což je vlastně případ vysvětlený v předchozí kapitole). Z dosavadních zkušeností by se tedy mohlo zdát, že vždy první volba, kterou Eclipse programátorovi nabídne, je ta správná. To však není vždy pravda, což se projeví hned u opravy druhé chyby...

Obrázek 5: Dialog zobrazený po stisku klávesové zkratky Ctrl+1 v okně „Problems“ u chyby „ArrayList cannot be resolved to a type“.

Poněkud složitější situace nastane ve chvíli, kdy se budeme snažit pomocí klávesové zkratky Ctrl+1 přidat chybějící import pro třídu List. Vývojové prostředí Eclipse v tomto případě zobrazí dialog s odlišnými možnostmi. Na prvních dvou řádcích se nabízí import tříd java.awt.List a java.util.List, takže si programátor musí dát pozor na to, jakou třídu ve skutečnosti má importovat. Jen pro zajímavost se můžeme podívat i na další nabízené volby, například změnu na třídu Line či Listener – Eclipse se v těchto případech opět snaží uhodnout, jaký je správný tvar (prozatím neznámého) identifikátoru.

Obrázek 6: Dialog zobrazený po stisku klávesové zkratky Ctrl+1 v okně „Problems“ u chyby „List cannot be resolved to a type“.

Odstranění nepotřebných importů

Integrované vývojové prostředí Eclipse taktéž umožňuje provést organizaci použitých importů, popř. odstranění těch importovaných balíčků a tříd, které nejsou ve zdrojovém textu zapotřebí. Organizace použitých importů spočívá v jejich seřazení, většinou takovým způsobem, že se nejdříve uvedou v abecedním pořadí importy tříd tvořících standardní API Javy, poté se uvádí (opět v abecedním pořadí) importy tříd z externích archivů a naposled pak importy tříd, které jsou deklarovány přímo v otevřeném projektu. Odstranění nepotřebných importů je založeno na analýze zdrojových kódů. Pokud nejsou některé balíčky nebo třídy ve zdrojovém kódu použity, zobrazí Eclipse varování, které je na rozdíl od chyby zvýrazněno žlutou barvou, namísto barvy červené.

Obrázek 7: Varování zobrazené ve zdrojovém kódu, který obsahuje dva nepotřebné importy. Třetí varování je poněkud odlišného charakteru – zvýrazňuje lokální proměnnou, která není nikde použita.

Pro odstranění nepoužívaných importů lze opět použít magickou klávesovou zkratku Ctrl+1, přičemž se v možnostech objeví nabídka pro pouhé odstranění importu, odstranění importu společně s přeorganizováním všech importů podle pravidel popsaných v předchozím odstavci, nebo lze alternativně do zdrojového kódu přidat anotaci typu @SuppressWarning, pomocí níž se varování skryje (obecně se však přikláním k tomu, aby se tento typ anotace používal pouze ve skutečně odůvodněných případech).

Obrázek 8: Dialog zobrazený po stisku klávesové zkratky Ctrl+1 ve chvíli, kdy se výběrový kurzor nachází nad jedním z nepoužívaných importů. Povšimněte si, že lze současně opravit obě varování – postačuje označit oba výběrové boxy ve spodní části dialogu.

Jednoduchý refaktoring – přesun příkazů do nové metody

Konečně se dostáváme k mnohem zajímavější a pro naprostou většinu programátorů velmi užitečné technologii – k podpoře takzvaného refaktoringu (refactoring). Integrované vývojové prostředí Eclipse totiž dokáže na žádost programátora měnit obsah zdrojových kódů, a to mnohdy i velmi radikálním způsobem. Mnoho změn je prováděno na globální úrovni celého projektu, což například znamená, že přejmenování metody je provedeno ve všech částech projektu, kde se tato metoda volá. Ovšem v žádném případě se nejedná o primitivní operaci typu „najdi a nahraď zadaný řetězec“, protože Eclipse dokáže v naprosté většině případů zjistit, kde je použita přejmenovávaná metoda a kde je naopak použita sice metoda stejného jména, ale patřící k jiné třídě.

Obrázek 9: Zdrojový text před provedením refaktoringu. Naší snahou bude přemístit všechny čtyři příkazy System.out.print() do samostatné metody. Program byl před provedením změn spuštěn a v dolní části okna Eclipse („Console“) je zobrazen text, který program vypsal na standardní výstup.

V této kapitole si ukážeme, jakým způsobem je možné přesunout jeden či několik vybraných příkazů do nové metody. Jedná se o poměrně často používaný způsob refaktoringu, který je založený na myšlence, že by každá metoda měla provádět jen jednu funkci, kterou lze v ideálním případě popsat jedinou větou v dokumentaci (resp. v JavaDocu). Pokud je popis funkce vykonávané metodou příliš dlouhý, znamená to, že metoda je zbytečně překomplikovaná a s velkou pravděpodobností je vhodné její tělo rozdělit do většího množství jednodušších metod. Důvod, proč někteří programátoři tento typ refaktoringu nedělají, spočívá v jeho obtížnosti v případě, že by se všechny změny musely ručně zapisovat v textovém editoru. Právě zde nám může pomoci Eclipse. Celý postup je vysvětlen na následující trojici obrázků:

Obrázek 10: Všechny příkazy, které se mají přenést do nové metody, se nejprve vyberou do bloku. Pro tuto operaci je možné použít myš, klávesy Shift+kurzorové šipky i další příkazy nabízené interním textovým editorem (Edit/Extract Selection To atd.).

Obrázek 11: Následně se v hlavním menu vybere příkaz Refactor/Extract Method. Pokročilejší uživatelé Eclipse namísto výběru příkazu z menu většinou používají klávesovou zkratku Alt+Shift+M. Zobrazí se první část dialogu, do něhož se zapíše jméno nové metody, a ve druhé části dialogu je ukázáno, které operace se skutečně provedou a jak se tyto operace projeví na obsahu zdrojového kódu. Pokud by se změna dotkla většího množství souborů, byly by všechny navrhované změny zobrazeny v horní části dialogu ve stromové struktuře.

Obrázek 12: Výsledek refaktoringu. Eclipse vytvořilo novou metodu, do níž byla přenesena vybraná čtveřice příkazů. Navíc bylo volání této metody doplněno do main(), takže se funkce programu nijak nezměnila. To je patrné i z obsahu okna „Console“, v němž je zobrazen výstup programu.

Změna parametrů metody na základě analýzy jejího volání

V úpravách demonstračního příkladu můžeme pokračovat dále. Metoda printSalutation() vytvořená pomocí postupu popsaného v předchozí kapitole není příliš obecná, protože vypisuje text pouze na standardní výstup představovaný třídou System.out. Ovšem úprava metody printSalutation() takovým způsobem, aby ji bylo možné použít například i pro tisk textu do souboru, je v Eclipse poměrně jednoduchá. Celý postup (založený na ručních úpravách i použití funkcí z Eclipse) je opět ukázán na sekvenci snímků obrazovky:

Obrázek 13: Po ručním doplnění parametru metody printSalutation() označí Eclipse celé volání metody za chybné, protože ve zdrojovém textu je sice deklarována stejně pojmenovaná metoda, ale ta je bezparametrická.

Obrázek 14: Po stisku klávesové zkratky Ctrl+1 se zobrazí nám již známý dialog Quick Fix, v němž Eclipse kromě několika dalších možností opravy chyby nabízí i přidání parametru do existující metody. Právě tuto možnost si vybereme. Povšimněte si, jaký typ parametru byl zvolen – je jím instance třídy PrintStream. Tento typ Eclipse zjistilo ze skutečně použitého parametru.

Obrázek 15: Po provedení opravy lze v metodě printSalutation() ručně odmazat slovo „System“, čímž se namísto volání metody System.out.print() bude volat metoda out.print(), kde out je parametr metody typu PrintStream.

Obrázek 16: Nyní je již možné metodu printSalutation(PrintStream out) volat s předáním libovolné instance třídy PrintStream, takže se tato metoda stala univerzálnější – lze ji použít například pro tisk do standardního výstupu, chybového výstupu, otevřeného souboru atd.