Repository: ycm-core/ycmd

Issue:
Code Completion for IOS project.
I'm trying to set up ycmd with completions for objective-c/iOS based from an xcode project. Semantic completions don't seem to be working.

I've set up a sample project here.
https://github.com/jojojames/DummyXcode

.ycm_extra_conf located here
https://github.com/jojojames/DummyXcode/blob/master/.ycm_extra_conf.py

compile_commands.json here
https://github.com/jojojames/DummyXcode/blob/master/compile_commands.json

I had a similar problem (using the same sample project as above) described here which was resolved through blacklisting some compile flags.
https://github.com/Andersbakken/rtags/issues/738

Not sure where to get a complete log (down to the clang error)
2016-06-28 10:45:16,497 - ERROR - Exception from semantic completer (using general): Traceback (most recent call last):
  File "/Users/james/.vim/dein/repos/github.com/Valloric/YouCompleteMe/third_party/ycmd/ycmd/../ycmd/handlers.py", line 112, in GetCompletions
    .ComputeCandidates( request_data ) )
  File "/Users/james/.vim/dein/repos/github.com/Valloric/YouCompleteMe/third_party/ycmd/ycmd/../ycmd/completers/completer.py", line 168, in ComputeCandidates
    candidates = self._GetCandidatesFromSubclass( request_data )
  File "/Users/james/.vim/dein/repos/github.com/Valloric/YouCompleteMe/third_party/ycmd/ycmd/../ycmd/completers/completer.py", line 184, in _GetCandidatesFromSubclass
    raw_completions = self.ComputeCandidatesInner( request_data )
  File "/Users/james/.vim/dein/repos/github.com/Valloric/YouCompleteMe/third_party/ycmd/ycmd/../ycmd/completers/cpp/clang_completer.py", line 112, in ComputeCandidatesInner
    raise RuntimeError( NO_COMPLETIONS_MESSAGE )
RuntimeError: No completions found; errors in the file?

Using a more barebones ycm file that only specifies flags gets 70-80% of completions working.
https://github.com/jojojames/.emacs.d/blob/master/lang/objc/ycm_conf.py



Discussion:
Thanks for the detailed report. can you grab the output of :YcmDebugInfo? Also, what is the output of :YcmDiags?

Ultimately, the set of flags passed to libclang means that it can't parse your files correctly. Either your extra conf is passing the wrong flags, or there is some other issue. Usually it is the former, though it looks like you're using a compilation database, so it could be that we need to blacklist more flags like the rtags folk (who also use libclang to parse your code)  

The extra diags will help us work that out. 

I'm using emacs-ycmd as a frontend for ycmd.

I tried opening the file in vim but got 'Native filetype completion not supported for current file, cannot force recompilation.' Might be something with my config for vim (haven't touched vim in a while).

Here's some debug info (just hunted around for some debug command `ycmd-show-debug-info'.
ycmd debug information for buffer AppDelegate.m in objc-mode:

Server has Clang support compiled in: True
Clang version: clang version 3.7.0 (tags/RELEASE_370/final)
Flags for /Users/james/Developer/DummyXcode/DummyXcode/AppDelegate.m loaded from /Users/james/Developer/DummyXcode/.ycm_extra_conf.py:
['/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang', '-x', 'c', '-x', 'objective-c', '-fmessage-length=0', '-fdiagnostics-show-note-include-stack', '-fmacro-backtrace-limit=0', '-std=gnu99', '-fobjc-arc', '-fmodules', '-fmodules-prune-interval=86400', '-fmodules-prune-after=345600', '-fbuild-session-file=/var/folders/k2/y7hdq90906d_5pgbt3_pt9jw0000gn/C/org.llvm.clang/ModuleCache/Session.modulevalidation', '-fmodules-validate-once-per-build-session', '-Wnon-modular-include-in-framework-module', '-Werror=non-modular-include-in-framework-module', '-Wno-trigraphs', '-fpascal-strings', '-Os', '-fno-common', '-Wno-missing-field-initializers', '-Wno-missing-prototypes', '-Werror=return-type', '-Wunreachable-code', '-Wno-implicit-atomic-properties', '-Werror=deprecated-objc-isa-usage', '-Werror=objc-root-class', '-Wno-arc-repeated-use-of-weak', '-Wduplicate-method-match', '-Wno-missing-braces', '-Wparentheses', '-Wswitch', '-Wunused-function', '-Wno-unused-label', '-Wno-unused-parameter', '-Wunused-variable', '-Wunused-value', '-Wempty-body', '-Wconditional-uninitialized', '-Wno-unknown-pragmas', '-Wno-shadow', '-Wno-four-char-constants', '-Wno-conversion', '-Wconstant-conversion', '-Wint-conversion', '-Wbool-conversion', '-Wenum-conversion', '-Wshorten-64-to-32', '-Wpointer-sign', '-Wno-newline-eof', '-Wno-selector', '-Wno-strict-selector-match', '-Wundeclared-selector', '-Wno-deprecated-implementations', '-DNS_BLOCK_ASSERTIONS=1', '-DOBJC_OLD_DISPATCH_PROTOTYPES=0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk', '-fstrict-aliasing', '-Wprotocol', '-Wdeprecated-declarations', '-miphoneos-version-min=9.3', '-g', '-fvisibility=hidden', '-Wno-sign-conversion', '-fembed-bitcode-marker', '-iquote', '/Users/james/Developer/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DummyXcode-generated-files.hmap', '-I/Users/james/Developer/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DummyXcode-own-target-headers.hmap', '-I/Users/james/Developer/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DummyXcode-all-target-headers.hmap', '-iquote', '/Users/james/Developer/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DummyXcode-project-headers.hmap', '-I/Users/james/Developer/DummyXcode/build/Release-iphoneos/include', '-I/Users/james/Developer/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DerivedSources/armv7', '-I/Users/james/Developer/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DerivedSources', '-F/Users/james/Developer/DummyXcode/build/Release-iphoneos', 'dependencies', '--serialize-diagnostics', '-resource-dir=/Users/james/.vim/dein/repos/github.com/Valloric/YouCompleteMe/third_party/ycmd/ycmd/../clang_includes', '-isystem', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1', '-isystem', '/usr/local/include', '-isystem', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include', '-isystem', '/usr/include', '-isystem', '/System/Library/Frameworks', '-isystem', '/Library/Frameworks']

Server running at: 127.0.0.1:63842

Maybe @abingham can point me in the right direction for the matching Emacs commands.

I was able to determine that the flag which causes `libclang` to barf is `-MT dependencies`.

I discovered this by trial and error, by manually setting flags in `.ycm_extra_conf.py`.

The net result is that I now get the "Could not build module 'UIKit'" error which you also reported to tags. I don't know how you solved that, so I can't really progress (modules are a dark magic to me), but I think it is clear that the issue is the set of flags passed to libclang, not an issue with YCM itself.

@r4nt @d0k  any clue why `-MT dependencies` might cause `libclang` to be unable to parse a file?

```
  -MT <value>             Specify name of main file output in depfile
```

Full flags are as above or more readable):

```
flags = [
  '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang',
  '-x', 'objective-c',
  '-arch', 'armv7',

  '-fmessage-length=0',
  '-fdiagnostics-show-note-include-stack',
  '-fmacro-backtrace-limit=0',
  '-std=gnu99',
  '-fobjc-arc',

  '-fmodules',
  '-fmodules-prune-interval=86400',
  '-fmodules-prune-after=345600',
  '-fbuild-session-file=' + os.tempnam(),
  '-fmodules-validate-once-per-build-session',

  '-Wnon-modular-include-in-framework-module',
  '-Werror=non-modular-include-in-framework-module',
  '-Wno-trigraphs',
  '-fpascal-strings',
  '-Os',
  '-fno-common',
  '-Wno-missing-field-initializers',
  '-Wno-missing-prototypes',
  '-Werror=return-type',
  '-Wunreachable-code',
  '-Wno-implicit-atomic-properties',
  '-Werror=deprecated-objc-isa-usage',
  '-Werror=objc-root-class',
  '-Wno-arc-repeated-use-of-weak',
  '-Wduplicate-method-match',
  '-Wno-missing-braces',
  '-Wparentheses',
  '-Wswitch',
  '-Wunused-function',
  '-Wno-unused-label',
  '-Wno-unused-parameter',
  '-Wunused-variable',
  '-Wunused-value',
  '-Wempty-body',
  '-Wconditional-uninitialized',
  '-Wno-unknown-pragmas',
  '-Wno-shadow',
  '-Wno-four-char-constants',
  '-Wno-conversion',
  '-Wconstant-conversion',
  '-Wint-conversion',
  '-Wbool-conversion',
  '-Wenum-conversion',
  '-Wshorten-64-to-32',
  '-Wpointer-sign',
  '-Wno-newline-eof',
  '-Wno-selector',
  '-Wno-strict-selector-match',
  '-Wundeclared-selector',
  '-Wno-deprecated-implementations',
  '-DNS_BLOCK_ASSERTIONS=1',
  '-DOBJC_OLD_DISPATCH_PROTOTYPES=0',

  '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk',

  '-fstrict-aliasing',
  '-Wprotocol',
  '-Wdeprecated-declarations',
  '-miphoneos-version-min=9.3',
  '-g',
  '-fvisibility=hidden',
  '-Wno-sign-conversion',
  '-fembed-bitcode-marker',

  '-iquote', '/Users/ben/Development/YouCompleteMe/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DummyXcode-generated-files.hmap',
  '-I/Users/ben/Development/YouCompleteMe/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DummyXcode-own-target-headers.hmap',
  '-I/Users/ben/Development/YouCompleteMe/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DummyXcode-all-target-headers.hmap',
  '-iquote', '/Users/ben/Development/YouCompleteMe/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DummyXcode-project-headers.hmap',
  '-I/Users/ben/Development/YouCompleteMe/DummyXcode/build/Release-iphoneos/include',
  '-I/Users/ben/Development/YouCompleteMe/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DerivedSources/armv7',
  '-I/Users/ben/Development/YouCompleteMe/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/DerivedSources',
  '-F/Users/ben/Development/YouCompleteMe/DummyXcode/build/Release-iphoneos',

  '-MMD',
#  '-MT', 'dependencies',
  '-MF', '/Users/ben/Development/YouCompleteMe/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/Objects-normal/armv7/AppDelegate.d',
  '--serialize-diagnostics', '/Users/ben/Development/YouCompleteMe/DummyXcode/build/DummyXcode.build/Release-iphoneos/DummyXcode.build/Objects-normal/armv7/AppDelegate.dia',
]
```

We can blacklist the depfiles-related flags I suppose, but I would like to understand a bit better before doing so.

Seems Rtags blacklists -MT also.

https://github.com/Andersbakken/rtags/commit/23c6c00fc70e6fa2b314e243cc75c9546a3c7e5f

@puremourning I believed we already put `-MT` to the blacklist 😕 

https://github.com/Valloric/ycmd/blob/master/ycmd/completers/cpp/flags.py#L46

@vheon you're quite right.

And it is broken somehow.

```
:YcmDebugInfo
...
'-F/Users/ben/Development/YouCompleteMe/DummyXcode/build/Release-iphoneos', 'dependencies',
```

It removed `-MT` but not `dependencies`.

@puremourning will you look into it? or should I?

I'll take a look now. 

OK i see the problem. 

`-MD` and `-MMD` are don't take a file argument, but we have said they do, which leads to malformed flag lists.

I'll prep a PR.

Having a left-over 'dependencies' in there would make it barf. The question is why you need to blacklist -MT (I see no reason why, as with -fsyntax-only the dep file will not be written anyway)


Resolving patch:
diff --git a/ycmd/completers/cpp/flags.py b/ycmd/completers/cpp/flags.py
--- a/ycmd/completers/cpp/flags.py
+++ b/ycmd/completers/cpp/flags.py
@@ -39,11 +39,19 @@
 
 # We need to remove --fcolor-diagnostics because it will cause shell escape
 # sequences to show up in editors, which is bad. See Valloric/YouCompleteMe#1421
-STATE_FLAGS_TO_SKIP = set(['-c', '-MP', '--fcolor-diagnostics'])
+STATE_FLAGS_TO_SKIP = set( [ '-c',
+                             '-MP',
+                             '-MD',
+                             '-MMD',
+                             '--fcolor-diagnostics' ] )
 
 # The -M* flags spec:
 #   https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Preprocessor-Options.html
-FILE_FLAGS_TO_SKIP = set(['-MD', '-MMD', '-MF', '-MT', '-MQ', '-o'])
+FILE_FLAGS_TO_SKIP = set( [ '-MF',
+                            '-MT',
+                            '-MQ',
+                            '-o',
+                            '--serialize-diagnostics' ] )
 
 # Use a regex to correctly detect c++/c language for both versioned and
 # non-versioned compiler executable names suffixes
@@ -266,9 +274,11 @@ def _RemoveUnusedFlags( flags, filename ):
   previous_flag_is_include = False
   previous_flag_starts_with_dash = False
   current_flag_starts_with_dash = False
+
   for flag in flags:
     previous_flag_starts_with_dash = current_flag_starts_with_dash
     current_flag_starts_with_dash = flag.startswith( '-' )
+
     if skip_next:
       skip_next = False
       continue
@@ -377,9 +387,9 @@ def _ExtraClangFlags():
   if OnMac():
     for path in MAC_INCLUDE_PATHS:
       flags.extend( [ '-isystem', path ] )
-  # On Windows, parsing of templates is delayed until instantation time.
-  # This makes GetType and GetParent commands not returning the expected
-  # result when the cursor is in templates.
+  # On Windows, parsing of templates is delayed until instantiation time.
+  # This makes GetType and GetParent commands fail to return the expected
+  # result when the cursor is in a template.
   # Using the -fno-delayed-template-parsing flag disables this behavior.
   # See
   # http://clang.llvm.org/extra/PassByValueTransform.html#note-about-delayed-template-parsing # noqa


Test patch:
diff --git a/ycmd/tests/clang/flags_test.py b/ycmd/tests/clang/flags_test.py
--- a/ycmd/tests/clang/flags_test.py
+++ b/ycmd/tests/clang/flags_test.py
@@ -28,6 +28,8 @@
 from mock import patch, Mock
 from ycmd.tests.test_utils import MacOnly
 
+from hamcrest import assert_that, contains
+
 
 @patch( 'ycmd.extra_conf_store.ModuleForSourceFile', return_value = Mock() )
 def FlagsForFile_BadNonUnicodeFlagsAreAlsoRemoved_test( *args ):
@@ -162,6 +164,27 @@ def RemoveUnusedFlags_RemoveFlagWithoutPrecedingDashFlag_test():
                                  filename ) )
 
 
+def RemoveUnusedFlags_Depfiles_test():
+  full_flags = [
+    '/bin/clang',
+    '-x', 'objective-c',
+    '-arch', 'armv7',
+    '-MMD',
+    '-MT', 'dependencies',
+    '-MF', 'file',
+    '--serialize-diagnostics', 'diagnostics'
+  ]
+
+  expected = [
+    '/bin/clang',
+    '-x', 'objective-c',
+    '-arch', 'armv7',
+  ]
+
+  assert_that( flags._RemoveUnusedFlags( full_flags, 'test.m' ),
+               contains( *expected ) )
+
+
 def RemoveUnusedFlags_RemoveFilenameWithoutPrecedingInclude_test():
   def tester( flag ):
     expected = [ 'clang', flag, '/foo/bar', '-isystem/zoo/goo' ]