protected void sendFiles(TernDoc doc) {
   if (doc.hasFiles()) {
     updateSentFiles(doc);
     // sync is performed asynchronously
     uploader.request(doc);
   }
 }
 @Override
 public void synchronizeFile(TernDoc doc, ITernFile file) throws IOException {
   writeLock.lock();
   try {
     try {
       TernQuery query = doc.getQuery();
       if (query != null) {
         if (TernResourcesManager.isJSFile(file)) {
           addJSFile(doc, file);
           sendFiles(doc);
           return;
         } else if (TernResourcesManager.isHTMLFile(file)) {
           // This is HTML file case: never keep the file on the server
           String queryType = query.getType();
           if (TernCompletionsQuery.isQueryType(queryType)
               || TernDefinitionQuery.isQueryType(queryType)
               || query instanceof TernLintQuery) {
             addHTMLFile(doc, file);
             return;
           }
         }
       }
       TernFile tf = file.toTernServerFile(getProject());
       String oldText = sentFiles.get(tf.getName());
       if (tf.getText().equals(oldText) && !uploader.cancel(tf.getName())) {
         // no need to synchronize the file, already up-to-date
         return;
       }
       doc.addFile(tf);
     } finally {
       updateSentFiles(doc);
       // as this is
       // wait a bit for the sync to finish
       uploader.join(TIMEOUT);
     }
   } finally {
     writeLock.unlock();
   }
 }
 @Override
 public void synchronizeFile(ITernFile file) throws IOException {
   writeLock.lock();
   try {
     TernFile tf = file.toTernServerFile(getProject());
     String oldText = sentFiles.get(tf.getName());
     if (tf.getText().equals(oldText) && !uploader.cancel(tf.getName())) {
       // no need to synchronize the file, already up-to-date
       return;
     }
     TernDoc doc = new TernDoc();
     doc.addFile(tf);
     sendFiles(doc);
   } finally {
     writeLock.unlock();
   }
 }