[gnome-code-assistance] [backends/c] Implement include file project support



commit 5e9157814148f920faf03f83cf0aca71d2e0a7d3
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Tue Nov 12 15:48:03 2013 +0100

    [backends/c] Implement include file project support

 backends/c/Makefile.am |    1 +
 backends/c/__init__.py |  146 +---------------------------------
 backends/c/service.py  |  209 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 213 insertions(+), 143 deletions(-)
---
diff --git a/backends/c/Makefile.am b/backends/c/Makefile.am
index 3986d9d..9f0f9a1 100644
--- a/backends/c/Makefile.am
+++ b/backends/c/Makefile.am
@@ -1,6 +1,7 @@
 cbackenddir = $(GCA_PYBACKENDS_DIR)/c
 cbackend_PYTHON =                              \
        backends/c/__init__.py                  \
+       backends/c/service.py                   \
        backends/c/clangimporter.py             \
        backends/c/makefileintegration.py       \
        backends/c/config.py
diff --git a/backends/c/__init__.py b/backends/c/__init__.py
index e400c18..493d74d 100644
--- a/backends/c/__init__.py
+++ b/backends/c/__init__.py
@@ -15,151 +15,11 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-from gnome.codeassistance.c import clangimporter, makefileintegration, config
-from gnome.codeassistance import transport, types
-
-import clang.cindex as cindex
-
-import glob, os
-
-def config_libclang():
-    libdir = config.llvm_libdir
-    cindex.Config.set_library_path(libdir)
-
-    files = glob.glob(os.path.join(libdir, 'libclang.so*'))
-
-    if len(files) != 0:
-        cindex.Config.set_library_file(files[0])
-
-class Service(transport.Service, transport.Project):
-    language = 'c'
-
-    def __init__(self):
-        super(Service, self).__init__()
-
-        self.index = cindex.Index.create(True)
-        self.makefile = makefileintegration.MakefileIntegration()
-
-    def _parse(self, doc, unsaved, options):
-        if (not doc.tu is None) and not self.makefile.changed_for_file(doc.path):
-            doc.tu.reparse(unsaved)
-        else:
-            args = self.makefile.flags_for_file(doc.path)
-
-            doc.tu = cindex.TranslationUnit.from_source(doc.path,
-                                                        args=args,
-                                                        unsaved_files=unsaved,
-                                                        index=self.index)
-
-        for u in unsaved:
-            u[1].close()
-
-        doc.process()
-        return doc
-
-    def parse_all(self, doc, docs, options):
-        unsaved = []
-        doc.diagnostics = []
-
-        for d in docs:
-            if d.data_path != d.path:
-                unsaved.append((d.path, open(d.data_path, 'rb')))
-
-        return [self._parse(doc, unsaved, options)]
-
-    def parse(self, doc, options):
-        if doc.data_path != doc.path:
-            unsaved = [(doc.path, open(doc.data_path, 'rb'))]
-        else:
-            unsaved = []
-
-        return self._parse(doc, unsaved, options)
-
-    def dispose(self, doc):
-        doc.tu = None
-
-class Document(transport.Document, transport.Diagnostics):
-    def __init__(self):
-        super(Document, self).__init__()
-        self.tu = None
-
-    def process(self):
-        self._process_diagnostics()
-
-    def _map_cseverity(self, severity):
-        s = types.Diagnostic.Severity
-
-        if severity == cindex.Diagnostic.Note:
-            return s.INFO
-        elif severity == cindex.Diagnostic.Warning:
-            return s.WARNING
-        elif severity == cindex.Diagnostic.Error:
-            return s.ERROR
-        elif severity == cindex.Diagnostic.Fatal:
-            return s.FATAL
-
-        return s.NONE
-
-    def _map_csource_location(self, location):
-        if location.file is None:
-            return None
-
-        if not os.path.samefile(self.path, location.file.name):
-            return None
-
-        return types.SourceLocation(line=location.line,
-                                    column=location.column)
-
-    def _map_csource_range(self, range):
-        start = self._map_csource_location(range.start)
-
-        if start is None:
-            return None
-
-        end = self._map_csource_location(range.end)
-
-        if end is None:
-            return None
-
-        return types.SourceRange(start=start, end=end)
-
-    def _map_cfixit(self, fixit):
-        range = self._map_csource_range(fixit.range)
-
-        if range is None:
-            return None
-
-        return types.Fixit(location=range, replacement=fixit.value)
-
-    def _map_cdiagnostic(self, d):
-        loc = self._map_csource_location(d.location)
-
-        if loc is None:
-            return None
-
-        severity = self._map_cseverity(d.severity)
-
-        ranges = [self._map_csource_range(r) for r in d.ranges]
-        ranges = list(filter(lambda x: not x is None, ranges))
-        ranges.insert(0, loc.to_range())
-
-        fixits = [self._map_cfixit(f) for f in d.fixits]
-        fixits = list(filter(lambda x: not x is None, fixits))
-
-        message = d.spelling
-
-        return types.Diagnostic(severity=severity,
-                                locations=ranges,
-                                fixits=fixits,
-                                message=message)
-
-    def _process_diagnostics(self):
-        diag = (self._map_cdiagnostic(d) for d in self.tu.diagnostics)
-        self.diagnostics = list(filter(lambda x: not x is None, diag))
+from gnome.codeassistance.c import service
+from gnome.codeassistance import transport
 
 def run():
-    config_libclang()
-    transport.Transport(Service, Document).run()
+    transport.Transport(service.Service, service.Document).run()
 
 if __name__ == '__main__':
     run()
diff --git a/backends/c/service.py b/backends/c/service.py
new file mode 100644
index 0000000..322f813
--- /dev/null
+++ b/backends/c/service.py
@@ -0,0 +1,209 @@
+# gnome code assistance c backend
+# Copyright (C) 2013  Jesse van den Kieboom <jessevdk gnome org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+from gnome.codeassistance.c import clangimporter, makefileintegration, config
+from gnome.codeassistance import transport, types
+
+import clang.cindex as cindex
+import glob, os
+
+_did_libclang_config = False
+
+def config_libclang():
+    global _did_libclang_config
+
+    if _did_libclang_config:
+        return
+
+    _did_libclang_config = True
+
+    libdir = config.llvm_libdir
+    cindex.Config.set_library_path(libdir)
+
+    files = glob.glob(os.path.join(libdir, 'libclang.so*'))
+
+    if len(files) != 0:
+        cindex.Config.set_library_file(files[0])
+
+class Service(transport.Service, transport.Project):
+    language = 'c'
+
+    def __init__(self):
+        super(Service, self).__init__()
+
+        config_libclang()
+
+        self.index = cindex.Index.create(True)
+        self.makefile = makefileintegration.MakefileIntegration()
+
+    def _parse(self, doc, docs, unsaved, options):
+        if (not doc.tu is None) and not self.makefile.changed_for_file(doc.path):
+            print('reparse')
+            doc.tu.reparse(unsaved)
+        else:
+            args = self.makefile.flags_for_file(doc.path)
+            print(doc.path, args)
+
+            doc.tu = cindex.TranslationUnit.from_source(doc.path,
+                                                        args=args,
+                                                        unsaved_files=unsaved,
+                                                        index=self.index)
+
+        for u in unsaved:
+            u[1].close()
+
+        return self._process(doc, docs)
+
+    def parse_all(self, doc, docs, options):
+        unsaved = [(d.path, open(d.data_path, 'rb')) for d in docs if d.data_path != d.path]
+        return self._parse(doc, docs, unsaved, options)
+
+    def parse(self, doc, options):
+        if doc.data_path != doc.path:
+            unsaved = [(doc.path, open(doc.data_path, 'rb'))]
+        else:
+            unsaved = []
+
+        self._parse(doc, unsaved, options)
+
+    def _included_docs(self, doc, docmap):
+        includes = doc.tu.get_includes()
+        retmap = {}
+
+        for i in includes:
+            p = os.path.realpath(i.include.name).decode('utf-8')
+
+            if p in docmap:
+                retmap[p] = docmap[p]
+                del docmap[p]
+
+        return retmap
+
+    def _process(self, doc, docs):
+        # Create a mapping from doc path to doc
+        docmap = {os.path.realpath(d.path): d for d in docs}
+
+        # Get the set of docs that were included during the processing
+        incdocs = self._included_docs(doc, docmap)
+
+        # Add also our own doc
+        incdocs[os.path.realpath(doc.path)] = doc
+
+        self._process_diagnostics(doc.tu, incdocs)
+
+        return list(incdocs.values())
+
+    def _process_diagnostics(self, tu, docmap):
+        for k, v in docmap.items():
+            v.diagnostics = []
+
+        resolved = {}
+
+        for d in tu.diagnostics:
+            if d.location is None or d.location.file is None:
+                continue
+
+            f = d.location.file.name.decode('utf-8')
+
+            try:
+                rf = resolved[f]
+            except KeyError:
+                rf = os.path.realpath(f)
+                resolved[f] = rf
+
+            try:
+                rdoc = docmap[rf]
+            except KeyError:
+                continue
+
+            rdoc.diagnostics.append(self._map_cdiagnostic(d))
+
+        for d in docmap:
+            print(d, docmap[d].diagnostics)
+
+    def dispose(self, doc):
+        doc.tu = None
+
+    def _map_cseverity(self, severity):
+        s = types.Diagnostic.Severity
+
+        if severity == cindex.Diagnostic.Note:
+            return s.INFO
+        elif severity == cindex.Diagnostic.Warning:
+            return s.WARNING
+        elif severity == cindex.Diagnostic.Error:
+            return s.ERROR
+        elif severity == cindex.Diagnostic.Fatal:
+            return s.FATAL
+
+        return s.NONE
+
+    def _map_csource_location(self, location):
+        return types.SourceLocation(line=location.line,
+                                    column=location.column)
+
+    def _map_csource_range(self, range):
+        start = self._map_csource_location(range.start)
+        end = self._map_csource_location(range.end)
+
+        return types.SourceRange(start=start, end=end)
+
+    def _map_cfixit(self, fixit):
+        range = self._map_csource_range(fixit.range)
+        return types.Fixit(location=range, replacement=fixit.value)
+
+    def _map_cdiagnostic(self, d):
+        loc = self._map_csource_location(d.location)
+        severity = self._map_cseverity(d.severity)
+
+        ranges = [self._map_csource_range(r) for r in d.ranges]
+        ranges = list(filter(lambda x: not x is None, ranges))
+        ranges.insert(0, loc.to_range())
+
+        fixits = [self._map_cfixit(f) for f in d.fixits]
+        fixits = list(filter(lambda x: not x is None, fixits))
+
+        message = d.spelling
+
+        return types.Diagnostic(severity=severity,
+                                locations=ranges,
+                                fixits=fixits,
+                                message=message)
+
+class Document(transport.Document, transport.Diagnostics):
+    def __init__(self):
+        super(Document, self).__init__()
+        self.tu = None
+
+    def process(self):
+        self._process_diagnostics()
+
+if __name__ == '__main__':
+    import sys
+
+    s = Service()
+    d = Document()
+
+    docs = [Document() for x in sys.argv[1:]]
+
+    for i, v in enumerate(sys.argv[1:]):
+        docs[i].path = os.path.abspath(v)
+        docs[i].data_path = docs[i].path
+
+    print(s.parse_all(docs[0], docs, {}))
+
+# ex:ts=4:et:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]