Commits

Ivan Vučica committed f324e7d

Code completion. Diagnostics. App description.

Comments (0)

Files changed (1)

 %%%%%%%%%%%%%%%%%%%%%%
 % Biblioteka libclang
 \chapter{Biblioteka libclang}
+\label{chap:libclang}
 
 Preferirani prevoditelj za programski jezik C koji se koristi u projektu
 LLVM zove se Clang. Po prelasku centralnog projekta GCC kojeg održava
 \end{lstlisting}
 
 \section{Prolazak po \textit{tokenima}}
+\label{lst:libclangtokeni}
+
 Tokeni ili simboli su rezultat leksičke analize.
 
 Prije prolaska po tokenima, potrebno je tokenizirati prijevodnu jedinicu.
 
 
 \section{Prolazak po kursorima}
+\label{sec:libclangkursori}
 Prolazak po kursorima, rezultatima sintaksne i semantičke analize, je
 kompleksniji nego prolazak po tokenima.
 
     }
 
 }
- \end{lstlisting}
+\end{lstlisting}
+
 \section{Autokompletiranje}
+\label{sec:libclangautocomplete}
+
+Za rukovanje autokompletiranjem, libclangu je potrebno predati lokaciju
+na kojoj se autokompletiranje treba izvršiti u obliku 
+\texttt{CXSourceLocation}. Pozivom na \texttt{clang\_codeCompleteAt()}
+izvršava se i djelomično reparsiranje prijevodne jedinice; no, bolji
+se rezultati postižu ako se prvo pozove 
+\texttt{clang\_reparseTranslationUnit()}.
+
+Kao rezultat dobivaju se svi tekstovi koje se očekuje da korisnik želi
+utipkati na navedenom mjestu. Navedene rezultate potrebno je sortirati s 
+\texttt{clang\_sortCodeCompletionResults()}. 
+
+Svaki rezultat uza sebe ima i prioritet. Korisniku je potrebno unaprijed
+odabrati rezultat s najboljim prioritetom.
+
+Svaki rezultat sastavljen je od više komadića \engl{chunk}. Navedeni
+komadići imaju svoju namjenu; primjerice, prefiks koji se ne ubacuje, ali
+služi za ispomoć kao dio brze dokumentacije. Primjer je povratna vrijednost
+funkcije prilikom utipkavanja poziva na funkciju. Također, Clang može
+predložiti privremene komadiće \engl{placeholder chunk} koje korisnik treba 
+zamijeniti nakon korištenja autokompletiranja. Primjerice, Xcode ubacuje te 
+komadiće kao plave kvadrate sa zaobljenim rubovima između kojih se korisnik
+prebacuje tipkom tab.
+
+Rezultati su poprilično opsežni, pa je možda uputno filtrirati ih po već
+unesenim znakovima; primjerice, možda je uputno izbaciti rezultate koji
+ne poćinju s "prin" ukoliko su to znakovi koje je korisnik već utipkao.
+
+Primjer upotrebe je u listingu \ref{lst:libclangcomplete}.
+
+\begin{lstlisting}[caption=Autokompletiranje,
+  label=lst:libclangcomplete,
+  float=htbp % http://tex.stackexchange.com/a/2282/25747
+]
+CXFile file = clang_getFile(clangTranslationUnit, 
+                            "/staza/do/objectivec/datoteke.m");
+CXSourceLocation location = clang_getLocationForOffset(
+                                clangTranslationUnit, file, 
+                                odmakOdPocetkaDatoteke);
+unsigned int line;
+unsigned int column;
+unsigned int offset;
+    
+clang_getSpellingLocation(location, &file, &line, &column, &offset);
+
+struct CXUnsavedFile unsavedFile;
+unsavedFile.Contents = izvorniKod;
+unsavedFile.Filename = "/staza/do/objectivec/datoteke.m";
+unsavedFile.Length = strlen(izvorniKod);
+
+CXCodeCompleteResults *results = clang_codeCompleteAt(
+                                     clangTranslationUnit,
+                                     "/staza/do/objectivec/datoteke.m",
+                                     line, column,
+                                     &unsavedFile, 1,
+                                     0);
+
+clang_sortCodeCompletionResults(results->Results, results->NumResults);
+
+for(int i = 0; i < results->NumResults; i++)
+{
+    CXCompletionResult result = results->Results[i];
+    CXCompletionString completion = result.CompletionString;
+        
+    char sugestija[1024] = { 0 };
+    for(int j = 0; j < clang_getNumCompletionChunks(completion); j++)
+    {
+        if(clang_getCompletionChunkKind(completion, j) != 
+               CXCompletionChunk_TypedText)
+            continue;
+        CXString string = clang_getCompletionChunkText(completion, j);
+        strcat(sugestija, clang_getCString(string);
+        clang_disposeString(string);
+    }
+        
+    unsigned priority = clang_getCompletionPriority(completion);
+    // ... uciniti nesto sa sugestijom i prioritetom ...
+}
+
+// ... prikazati korisniku rezultate ...
+
+clang_disposeCodeCompleteResults(results);
+
+\end{lstlisting}
 
+\section{Dijagnostika}
+Prilikom parsiranja, libclang može zapamtiti neke dijagnostičke opaske.
+To mogu biti greške, upozorenja ili nešto slično. Ponekad može čak
+ponuditi i rješenje za opasku; primjerice, ukoliko nedostaje točka-zarez,
+može klijentskoj aplikaciji opisati gdje i kako ubaciti točka-zarez.
+
+Primjer vrlo jednostavnog ispisivanja dijagnostike za pojedinu prijevodnu 
+jedinicu dan je u listingu \ref{lst:libclangdiag}.
+
+\begin{lstlisting}[caption=Dijagnostika,
+  label=lst:libclangdiag,
+  float=htbp % http://tex.stackexchange.com/a/2282/25747
+]
+void printDiagnostics()
+{
+    int num = clang_getNumDiagnostics(clangTranslationUnit);
+    for(int i = 0; i < num; i++)
+    {
+        CXDiagnostic d = clang_getDiagnostic(clangTranslationUnit, i);
+        CXString s = clang_formatDiagnostic(d,
+                         clang_defaultDiagnosticDisplayOptions());
+        fprintf(stderr, "%s\n", clang_getCString(s));
+        clang_disposeString(s);
+        clang_disposeDiagnostic(d);
+    }
+}
+\end{lstlisting}
 
 %%%%%%%%%%%%%%%%%
 % Pregled aplikacije
 
 "Editor Teksta" je minimalistički uređivač teksta s podrškom za kolorizaciju
 sintakse. Izgrađen je koristeći dokumentnu arhitekturu sustava Cocoa,
-a za obradu izvornog koda i bojanje sintakse koristi libclang.
+a za obradu izvornog koda, bojanje sintakse i autokompletiranje koristi 
+libclang.
+
+\section{Podržani formati i jezici}
+U Info.plist specificirana je podrška za sljedeće formate:
+
+\begin{itemize}
+\item .c, .cpp, .m, .mm: Jezici C, C++, Objective-C i Objective-C++.
+(Postoji podrška i za dodatne ekstenzije.) Otvaranje se vrši 
+\texttt{NSDocument} podklasom \texttt{IVDocument}.
+\item .txt, .rtf: Tekstualne i Rich Text Format datoteke. Otvaranje se vrši
+\texttt{NSDocument} podklasom \texttt{IVSourceCodeDocument}.
+\end{itemize}
+
+Podrška za .txt i .rtf je minimalna i svodi se na ubacivanje teksta u
+\texttt{NSTextView} i spremanje istog u datoteku.
+
+Podrška za programske jezike je nešto veća. Primjerice, omogućuje se 
+preciziranje drugačijih opcija za kompajler u postavkama, a klasa
+\texttt{IVSourceCodeDocument} dodatno koristi i libclang za parsiranje
+koda. Rezultate koristi za bojanje.
+
+Sadržaj \texttt{NSTextView}-a je \textit{bindan} na \textit{instance} 
+varijablu s kojom se ustvari po potrebi manipulira iz koda.
+
+Obje klase spremaju i učitavaju koristeći \texttt{dataOfType:error:} i
+\texttt{readFromData:ofType:error:}.
+
+\section{Bojanje sintakse}
+Bojanje sintakse vrši se prolaskom kroz tokene kako je opisano u sekciji 
+\ref{sec:libclangtokeni} i prolaskom kroz kursore kako je opisano u
+sekciji \ref{sec:libclangkursori}.
+
+Dohvaća se instanca klase \texttt{NSMutableAttributedString}, te se izrađuje
+kopija kojoj se uklanjaju svi atributi. Ovo se čini radi jednostavnosti;
+ispravnije bi bilo mijenjati originali \texttt{NSMutableAttributedString}.
+Jedna od posljedica je i to da se gubi fokus, lokacija kursora za unos teksta
+i pozicija \texttt{NSScrollView}-a.
+
+Zatim se iterira kroz tokene i kursore, te se na osnovu vrste tokena i kursora
+kreira atribut za boju kojem je naziv \texttt{NSForegroundColorAttributeName},
+ako je tip tokena odnosno kursora odgovarajući. U navedene tokene se sprema
+Objective-C objekt tipa \texttt{NSColor}; to omogućuje da se postavljanjem
+varijable na \texttt{NULL} jednostavno signalizira kako se boja tokena
+odnosno kursora ne treba mijenjati.
+
+\section{Autokompletiranje}
+Autokompletiranje se vrši postavljanjem delegata za \texttt{NSTextView}
+na instancu klase \texttt{IVSourceListDocument}. To izaziva pozivanje
+delegat-metode
+\texttt{textView:completions:forPartialWordRange:indexOfSelectedItem:}.
+
+\texttt{NSTextView} već ima ugrađen mehanizam za autokompletiranje riječi,
+te se automatski povezuje s rječnikom engleskih riječi ugrađenim u
+operacijski sustav. Navedene riječi nalaze se u nizu \engl{array} koji je
+dan kao argument \texttt{completions}. Te riječi ćemo ignorirati.
+
+Raspon znakova koji se želi zamijeniti dan je kao \texttt{NSRange},
+\textit{plain old data} C struktura koja sadrži lokaciju i duljinu raspona.
+Navedeni raspon možemo koristiti kako bismo znali kojim prefiksom ćemo
+filtrirati rezultate koje nam vrati libclang. Primjerice, ukoliko je korisnik
+utipkao "voi" i pritisnuo tipku za autokompletiranje (tipka ESC),
+želimo samo rezultate koji počinju s "voi". To će biti, recimo, ključna riječ
+"void".
+
+Kao argument \texttt{indexOfSelectedItem} dan je pokazivač na 
+\texttt{NSInteger}. Taj tip podataka je definiran kao C-ov \texttt{long}.
+Činjenica da smo dobili pokazivač indicira nam da se očekuje povratak
+vrijednosti kroz ovaj argument. Kad vratimo niz stringova koji će služiti
+kao ponuda korisniku za odabir željenog \textit{complete} stringa,
+\texttt{indexOfSelectedItem} je redni broj automatski odabrane stavke od
+svih koje će biti ponuđene.
+
+Implementacija ove delegat-metode sadrži tehnike opisane u
+sekciji \ref{sec:libclangcomplete}, uz dodatnu heuristiku za pokušaj odabira
+najpovoljnijeg rezultata.
+
+\section{Dijagnostika}
+Pri dnu prozora postavljen je \texttt{NSTableView} za dijagnostiku. Navedena
+tablica je \textit{bindana} na \texttt{NSArrayController}. Navedenom
+kontroleru puni se svojstvo \texttt{content} s rezultatima dijagnostike
+u obliku \texttt{NSDictionary}-ja napunjenih stringovima. Pojedine vrijednosti
+u stavkama služe za punjenje pojedinih stupaca tablice.
+
+Obnavljanje \textit{arraya} \texttt{content} u \texttt{NSArrayController}-u
+vrši se u metodu \texttt{refreshDiagnostics} koja se poziva, između ostalog,
+pri reparsiranju prijevodne jedinice.
 
 %%%%%%%%%%%
 % Zaključak