Aptana Journal #5: Perbaikan


Hari ini saya akan melanjutkan memperbaiki perubahan sebelumnya.  Bila terdapat lebih dari satu versi proposal content assist yang ditemukan, misalnya hasil parsing dari file JavaScript dan hasil parsing dari file ScriptDoc XML, maka saya hanya akan memakai versi yang memiliki dokumentasi.  Proposal content assist tanpa dokumentasi hanya akan dipakai bila tidak ada versi terdokumentasi yang ditemukan.

Untuk mencapai hasil di atas, saya perlu mengubah method addProjectGlobals() di class JSContentAssistProcessor. Bila sebelumnya isi method ini akan menambahkan seluruh PropertyElement yang ditemukan ke dalam Set proposal, maka saya akan mengubahnya untuk melakukan penyaringan seperti yang terlihat pada kode program berikut ini:

private void addProjectGlobals(Set<ICompletionProposal> proposals, int offset)
{
    Collection<PropertyElement> projectGlobals = indexHelper.getGlobals(getIndex(), getProject(), getFilename());

    if (!CollectionsUtil.isEmpty(projectGlobals))
    {
       String[] userAgentNames = getActiveUserAgentIds();
       URI projectURI = getProjectURI();

       // Tampung dulu seluruh FunctionElement yang akan diproses            
       List<FunctionElement> listFunctionElement = new ArrayList<FunctionElement>();
       for (PropertyElement property: CollectionsUtil.filter(projectGlobals, isVisibleFilter)) {
         if (property instanceof FunctionElement) {
           listFunctionElement.add((FunctionElement)property);
         }                
       }

       for (PropertyElement property : CollectionsUtil.filter(projectGlobals, isVisibleFilter))
       {

          // Hanya akan menyertakan proposal yang tidak mengandung informasi yang jelas
          // jika versi yang lebih terdokumentasi tidak tersedia.
          if (property instanceof FunctionElement) {                    
              FunctionElement thisFunctionElement = (FunctionElement) property;                    
              if (thisFunctionElement.getDescription()==null || thisFunctionElement.getDescription().length()==0) {
                 boolean ketemuYangTerdokumentasi = false;
                 for (FunctionElement item: listFunctionElement) {
                     // Mencari versi yang sudah terdokumentasi 
                     if (thisFunctionElement.getName().equals(item.getName()) && item.getDescription()!=null && item.getDescription().length()>0) {
                        ketemuYangTerdokumentasi = true;
                     }
                 }
                 if (ketemuYangTerdokumentasi) continue;
              }
          }
          String location = null;                
          List<String> documents = property.getDocuments();
          if (!CollectionsUtil.isEmpty(documents))
          {
             String docString = documents.get(0);
             int index = docString.lastIndexOf('/');
             if (index != -1)
             { 
                 location = docString.substring(index + 1);
             }
             else
             {
                 location = docString;
             }
          }
          addProposal(proposals, property, offset, projectURI, location, userAgentNames);
       }
    }
}

Setelah ini, saya ingin agar ketika sebuah proposal content assist dipilih oleh pengguna, maka context info (dokumentasi) untuk content assist tersebut langsung ditampilkan.  Hal ini berbeda dengan pendekatan Aptana Studio saat ini dimana context info hanya akan muncul setelah user mengetik tanda kurung buka.  Nilai context info saat ini diambil secara terpisah dari content assist seperti yang saya bahas di jurnal 2.

Apakah nilai context info tidak bisa diambil dari content assist?  Sepertinya bisa, karena saya melihat bahwa class CommonCompletionProposal memiliki sebuah atribut _contextInformation yang bertipe IContextInformation.

Lalu, bagaimana caranya supaya bisa memakai _contextInformation tersebut?  Untuk menjawab pertanyaan, ini saya menelusuri kode program untuk mencari tahu apa yang dikerjakan ketika sebuah proposal content asssist dipilih dan dipakai.   Method yang dipanggil adalah insertProposal() di class ContentAssistant.  Berikut ini adalah cuplikan di akhir dari method tersebut:

private void insertProposal(ICompletionProposal p, char trigger, int stateMask, final int offset)
{
  ... // kode diabaikan
  try
  {
     ... // kode diabaikan

     IContextInformation info = p.getContextInformation();
     if (info!=null)
     {
         ... // kode diabaikan
         fContentAssistant.showContextInformation(info, contextInformationOffset);
     }
     else
     {
         fContentAssistant.showContextInformation(null, -1);
     }
  }
  finally
  {
     ... // kode diabaikan
  }
}

Ternyata context info untuk sebuah proposal content assist akan ditampilkan secara otomatis bila ditemukan.  Yang terjadi adalah saat ini, content assist tidak memiliki context info.  Jadi, saya perlu menambahkan context info ke dalam setiap proposal untuk FunctionElement.  Selain itu, karena setiap fungsi dipanggil dengan kurung buka dan kurung tutup, saya akan menambahkan kurung buka dan kurung tutup untuk setiap proposal FunctionElement dimana posisi kursor harus berada di dalam kurung.  Ehem, fitur ini cukup berguna bagi saya, kenapa Aptana Studio tidak memberikannya?  Well, etika berkata bahwa tidak sopan mencela sebuah produk open-source; bila saya merasa ada yang kurang, maka saya harus menggunakan otak untuk memperbaiki kekurangan tersebut, bukan menggunakan mulut untuk mencela sesuatu yang diberikan pada saya secara bebas🙂

Untuk mendukung context info pada proposal sebuah method/function, maka saya menambahkan sebuah constructor baru di PropertyElementProposal seperti berikut ini:

public PropertyElementProposal(String replacementString, int cursorPosition, PropertyElement property,
  int offset, int replaceLength, URI uri, ContextInformation contextInformation)
{
   super(replacementString, offset, replaceLength, cursorPosition, null, property.getName(), 
         contextInformation, null);
   this.property = property;
   this.uri = uri;
}

Setelah itu, pada bagian yang menambahkan proposal, yaitu di method addProposal() di class JSContentAssistProcessor, saya mengubah dan menyisipkan kode program seperti berikut ini:

PropertyElementProposal proposal = null;
if (property instanceof FunctionElement) {
  String documentation = JSModelFormatter.CONTEXT_INFO.getDocumentation(property);
  ContextInformation contextInformation = new ContextInformation(property.getName(), documentation);
  proposal = new PropertyElementProposal(property.getName()+"()", property.getName().length()+1, property,
    offset, replaceLength, projectURI, contextInformation);
} else {
  proposal = new PropertyElementProposal(property, offset, replaceLength, projectURI);
}

Pada kode program di atas, saya sangat terbantu oleh class JSModelFormatter yang dapat menghasilkan dokumentasi yang telah ter-format secara rapi dan tinggal ditampilkan.

Gambar berikut ini memperlihatkan apa yang terjadi ketika saya menambahkan content assist dan memilihnya:

Tampilan Content Assist Dan Context Info

Tampilan Content Assist Dan Context Info

Perihal Solid Snake
I'm nothing...

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: