Beispiel #1
0
    def test(parse_builtins):
        # type: (...) -> None
        root = tempfile.mkdtemp()
        server = DummyServer(Path(root))

        with tempfile.NamedTemporaryFile(suffix=".vhd") as filename:
            diags = server.getMessagesWithText(
                Path(filename.name),
                "library lib; use lib.pkg.all; library builtin; use builtin.foo;",
            )

            parse_builtins.assert_called()

            logIterable("Diags", diags, _logger.info)

            it.assertCountEqual(
                diags,
                [
                    UnresolvedDependency(
                        RequiredDesignUnit(
                            name=Identifier("pkg"),
                            library=Identifier("lib"),
                            owner=Path(filename.name),
                            locations=[Location(0, 17)],
                        ),
                        Location(0, 17),
                    )
                ],
            )
Beispiel #2
0
        def test():
            path = _Path(TEST_PROJECT, "another_library", "foo.vhd")

            numeric_std = RequiredDesignUnit(
                name=Identifier("numeric_std"),
                library=Identifier("ieee"),
                owner=path,
                locations=(),
            )

            it.assertIs(it.project.resolveDependencyToPath(numeric_std), None)
Beispiel #3
0
 def test_DependencyInfoForPathNotFound(self):
     path = Path(p.join(TEST_PROJECT, "another_library", "foo.vhd"))
     dependency = RequiredDesignUnit(
         name=Identifier("clock_divider"),
         library=Identifier("basic_library"),
         owner=path,
         locations=(),
     )
     self.assertEqual(
         self.server._getDependencyInfoForHover(dependency),
         "Couldn't find a source defining 'basic_library.clock_divider'",
     )
Beispiel #4
0
 def test_ReportDependencyInfo(self):
     path = Path(p.join(TEST_PROJECT, "another_library", "foo.vhd"))
     dependency = RequiredDesignUnit(
         name=Identifier("clock_divider"),
         library=Identifier("basic_library"),
         owner=path,
         locations=(),
     )
     self.assertEqual(
         self.server._getDependencyInfoForHover(dependency),
         'Path "some_path", library "some_library"',
     )
Beispiel #5
0
        def test():
            path = _Path(TEST_PROJECT, "basic_library",
                         "package_with_functions.vhd")

            clock_divider = RequiredDesignUnit(
                name=Identifier("package_with_functions"),
                library=Identifier("basic_library"),
                owner=path,
                locations=(),
            )

            it.assertEqual(
                it.project.resolveDependencyToPath(clock_divider),
                (path, Identifier("basic_library")),
            )
Beispiel #6
0
    def getLibrary(self, path):
        # type: (Path) -> UnresolvedLibrary
        """
        Gets the library the path is in, inferring and updating it if needed.
        Any unit that can be used from VHDL code can be bound to a library,
        even if Verilog and SystemVerilog don't have this concept.
        """
        self._parseSourceIfNeeded(path)

        if path not in self.paths:
            # Add the path to the project but put it on a different library
            self._parseSourceIfNeeded(path)
            self._updatePathLibrary(path, Identifier("not_in_project", True))
            # Report paths that are valid (that is, not temporary) when they
            # can't be found in the project file
            if not isinstance(path, TemporaryPath):
                self._addDiagnostic(PathNotInProjectFile(path))

        elif path not in self._library_map:
            # Library is not defined, try to infer
            _logger.info("Library for '%s' not set, inferring it", path)
            library = self._inferLibraryForPath(path)
            if library is not None:
                self._updatePathLibrary(path, library)

        return self._library_map.get(path, None)
Beispiel #7
0
    def addSource(self, path, library, single_flags=None, dependencies_flags=None):
        # type: (Path, Optional[str], Optional[BuildFlags], Optional[BuildFlags]) -> None
        """
        Adds a source to the database, triggering its parsing even if the
        source has already been added previously
        """
        _logger.info(
            "Adding %s, library=%s, flags=(single=%s, dependencies=%s)",
            path,
            library,
            single_flags,
            dependencies_flags,
        )
        self._paths.add(path)
        self._flags_map[path] = {
            BuildFlagScope.single: tuple(single_flags or ()),
            BuildFlagScope.dependencies: tuple(dependencies_flags or ()),
        }
        if library is not None:
            self._library_map[path] = Identifier(
                library, case_sensitive=FileType.fromPath(path) != FileType.vhdl
            )

        # TODO: Parse on a process pool
        self._parseSource(path)
Beispiel #8
0
        def test():
            path = _Path(TEST_PROJECT, "another_library", "foo.vhd")

            clock_divider = RequiredDesignUnit(
                name=Identifier("clock_divider"),
                library=Identifier("basic_library"),
                owner=path,
                locations=(),
            )

            it.assertEqual(
                it.project.resolveDependencyToPath(clock_divider),
                (
                    _Path(TEST_PROJECT, "basic_library", "clock_divider.vhd"),
                    Identifier("basic_library"),
                ),
            )
Beispiel #9
0
    def __init__(
            self,
            design_units,  # type: Iterable[Dict[str, str]]
            library=None,  # type: str
            dependencies=None,  # type: Iterable[MockDep]
            filename=None,  # type: Optional[str]
    ):

        self._design_units = list(design_units or [])

        if filename is not None:
            self._filename = Path(p.join(self.base_path, filename))
        else:
            library = "lib_not_set" if library is None else library
            self._filename = Path(
                p.join(
                    self.base_path,
                    library,
                    "_{}.vhd".format(self._design_units[0]["name"]),
                ))

        self.filetype = FileType.fromPath(self.filename)
        #  self.abspath = p.abspath(self.filename)
        self.flags = []  # type: ignore

        self.library = library
        self._dependencies = []  # type: List[RequiredDesignUnit]
        for dep_spec in dependencies or []:
            _name = dep_spec[0]
            _library = "work"

            try:
                _library, _name = dep_spec  # type: ignore
            except ValueError:
                pass

            self._dependencies.append(
                RequiredDesignUnit(
                    self._filename,
                    Identifier(_name, False),
                    Identifier(_library, False),
                ))

        self._createMockFile()
Beispiel #10
0
    def test_GetRebuilds(self, rebuild_info, expected):
        # type: (...) -> Any
        _logger.info("Rebuild info is %s", rebuild_info)
        library = Identifier("some_lib", False)
        with patch.object(self.builder,
                          "_searchForRebuilds",
                          return_value=[rebuild_info]):
            self.builder._database.getDependenciesByPath = MagicMock(
                return_value=[
                    RequiredDesignUnit(
                        owner=Path(""),
                        name=Identifier("very_common_pkg"),
                        library=Identifier("work"),
                    )
                ])

            self.assertCountEqual(
                self.builder._getRebuilds(_source("source.vhd"), "", library),
                {expected},
            )
Beispiel #11
0
 def _parseBuiltinLibraries(self):
     "(Not used by XVHDL)"
     return (Identifier(x, case_sensitive=False) for x in (
         "ieee",
         "std",
         "unisim",
         "xilinxcorelib",
         "synplify",
         "synopsis",
         "maxii",
         "family_support",
     ))
Beispiel #12
0
    def _getRebuilds(self, path, line, library):
        # type: (Path, str, Identifier) -> Set[RebuildInfo]
        """
        Gets info on what should be rebuilt to satisfy the builder
        """
        try:
            parse_results = self._searchForRebuilds(line)
        except NotImplementedError:  # pragma: no cover
            return set()

        rebuilds = set()  # type: Set[RebuildInfo]
        for rebuild in parse_results:
            unit_type = rebuild.get("unit_type", None)  # type: str
            library_name = rebuild.get("library_name", None)  # type: str
            unit_name = rebuild.get("unit_name", None)  # type: str
            rebuild_path = rebuild.get("rebuild_path", None)  # type: str

            if None not in (unit_type, unit_name):
                for dependency in self._database.getDependenciesByPath(path):
                    if dependency.name.name == rebuild["unit_name"]:
                        rebuilds.add(
                            RebuildUnit(Identifier(unit_name),
                                        DesignUnitType(unit_type)))
                        break
            elif None not in (library_name, unit_name):
                if library_name == "work":
                    library_name = library.name
                rebuilds.add(
                    RebuildLibraryUnit(Identifier(unit_name),
                                       Identifier(library_name)))
            elif rebuild_path is not None:
                # GHDL sometimes gives the full path of the file that
                # should be recompiled
                rebuilds.add(RebuildPath(Path(rebuild_path)))
            else:  # pragma: no cover
                self._logger.warning("Don't know what to do with %s", rebuild)

        return rebuilds
Beispiel #13
0
    def test_VhdlCompilation(self, *args):
        # type: (...) -> Any
        if FileType.vhdl not in self.builder.file_types:
            raise unittest2.SkipTest("Builder {} doesn't support VHDL".format(
                self.builder_name))

        source = _source("no_messages.vhd")
        records, rebuilds = self.builder.build(source, Identifier("work"),
                                               BuildFlagScope.single)
        self.assertNotIn(
            DiagType.ERROR,
            [x.severity for x in records],
            "This source should not generate errors.",
        )
        self.assertFalse(rebuilds)
Beispiel #14
0
def getVunitSources(builder):
    # type: (AnyValidBuilder) -> Iterable[Tuple[Path, Optional[str], BuildFlags]]
    "Gets VUnit sources according to the file types supported by builder"
    if not foundVunit():
        return

    _logger.debug("VUnit installation found")

    sources = []  # type: List[vunit.source_file.SourceFile]

    # Prefer VHDL VUnit
    if FileType.vhdl in builder.file_types:
        sources += _getSourcesFromVUnitModule(VUnit_VHDL)
        _logger.debug("Added VUnit VHDL files")

    if FileType.systemverilog in builder.file_types:
        _logger.debug("Builder supports Verilog, adding VUnit Verilog files")
        builder.addExternalLibrary(FileType.verilog,
                                   Identifier("vunit_lib", False))
        sources += _getSourcesFromVUnitModule(VUnit_Verilog)

    if not sources:
        _logger.info("Vunit found but no file types are supported by %s",
                     builder)
        return

    for source in sources:
        path = p.abspath(source.name)
        library = source.library.name

        # Get extra flags for building VUnit sources
        try:
            flags = _VUNIT_FLAGS[BuilderName(
                builder.builder_name)][source.vhdl_standard]
        except KeyError:
            flags = tuple()

        yield Path(path), library, flags

    if FileType.systemverilog in builder.file_types:
        for path in findRtlSourcesByPath(Path(p.dirname(vunit.__file__))):
            if _isHeader(path):
                yield Path(path), None, ()
Beispiel #15
0
    def _buildAndGetDiagnostics(
        self, path, library, flags
    ):  # type: (Path, Identifier, BuildFlags) -> Tuple[Set[CheckerDiagnostic],Set[RebuildInfo]]
        """
        Runs _buildSource method and parses the output to find message
        records and units that should be rebuilt
        """
        if library is None:
            library = self._database.getLibrary(path)  # or Identifier("work")

        self._createLibraryIfNeeded(library)

        for lib in (x.library
                    for x in self._database.getDependenciesByPath(path)):
            self._createLibraryIfNeeded(lib or Identifier("work"))

        diagnostics = set()  # type: Set[CheckerDiagnostic]
        rebuilds = set()  # type: Set[RebuildInfo]

        for line in self._buildSource(path, library, flags=flags):
            if self._shouldIgnoreLine(line):
                continue

            for record in self._makeRecords(line):
                try:
                    # If no filename is set, assume it's for the current path
                    if record.filename is None:
                        diagnostics.add(record.copy(filename=path))
                    else:
                        diagnostics.add(record)
                except:
                    self._logger.exception(
                        " - %s hash: %s | %s",
                        record,
                        record.__hash__,
                        type(record).__mro__,
                    )
                    raise
            rebuilds |= self._getRebuilds(path, line, library)

        self._logBuildResults(diagnostics, rebuilds)

        return diagnostics, rebuilds
Beispiel #16
0
    def _parseBuiltinLibraries(self):
        # type: (...) -> Any
        """
        Discovers libraries that exist regardless before we do anything
        """
        for line in runShellCommand(["ghdl", "--dispconfig"]):
            library_path_match = self._scan_library_paths.search(line)
            if library_path_match:
                library_path = library_path_match.groupdict()["library_path"]
                self._logger.debug("library path is %s", library_path)

                # Up to v0.36 ghdl kept libraries at
                #   <library_path>/<vhdl starndard>/<name>
                # but his has been changed to
                #   <library_path>/<name>/<vhdl starndard>
                libraries_paths = glob(
                    p.join(library_path, "v93", "*")
                    if self._version < "0.36"
                    else p.join(library_path, "*")
                )

                for path in filter(p.isdir, libraries_paths):
                    name = path.split(p.sep)[-1]
                    yield Identifier(name.strip(), case_sensitive=False)
Beispiel #17
0
 def test_CreateLibraryMultipleTimes(self):  # pylint: disable=invalid-name
     # type: (...) -> Any
     self.builder._createLibraryIfNeeded(Identifier("random_lib"))
     self.builder._createLibraryIfNeeded(Identifier("random_lib"))
Beispiel #18
0
 def builtin_libraries(_):
     return (Identifier("ieee"), )
Beispiel #19
0
class TestValidProject(TestCase):

    params = {
        "rootUri": uris.from_fs_path(TEST_PROJECT),
        "initializationOptions": {"project_file": "config.json"},
    }

    def setUp(self):
        setupTestSuport(TEST_TEMP_PATH)

        _logger.debug("Creating server")
        tx_r, tx_w = os.pipe()
        self.tx_stream_reader = JsonRpcStreamReader(os.fdopen(tx_r, "rb"))

        rx_stream = MagicMock()
        rx_stream.closed = False

        self.server = lsp.HdlCheckerLanguageServer(rx_stream, os.fdopen(tx_w, "wb"))

        # Initialize server
        _logger.info("Calling m_initialize")
        self.assertEqual(
            self.server.m_initialize(**(self.params or {})),
            {
                "capabilities": {
                    "textDocumentSync": 1,
                    "definitionProvider": True,
                    "hoverProvider": True,
                    "referencesProvider": True,
                }
            },
        )

        _logger.info("Calling m_initialized")
        with patch("hdl_checker.lsp.onNewReleaseFound"):
            self.assertIsNone(self.server.m_initialized())

    def teardown(self):
        _logger.debug("Shutting down server")
        msg = LSP_MSG_TEMPLATE.copy()
        msg.update({"method": "exit"})
        self.server._endpoint.consume(msg)

        # Close the pipe from the server to stdout and empty any pending
        # messages
        self.tx_stream_reader.close()
        self.tx_stream_reader.listen(_logger.fatal)

        del self.server

    def _checkLintFileOnOpen(self, source):
        return self._checkLintFileOnMethod(source, "m_text_document__did_open")

    def _checkLintFileOnSave(self, source):
        return self._checkLintFileOnMethod(source, "m_text_document__did_save")

    def _checkLintFileOnMethod(self, source, method):
        with patch.object(self.server.workspace, "publish_diagnostics"):
            _logger.info("Sending %s request", method)
            getattr(self.server, method)(
                textDocument={"uri": unicode(uris.from_fs_path(source)), "text": None}
            )

            mock_call = _waitOnMockCall(self.server.workspace.publish_diagnostics)
            doc_uri, diagnostics = mock_call[1]
            _logger.info("doc_uri: %s", doc_uri)
            _logger.info("diagnostics: %s", diagnostics)

            self.assertEqual(doc_uri, uris.from_fs_path(source))
            return diagnostics

    def test_LintFileOnOpening(self):
        source = p.join(TEST_PROJECT, "basic_library", "clk_en_generator.vhd")
        with patch(
            "hdl_checker.lsp.Server.getMessagesByPath",
            return_value=[CheckerDiagnostic(filename=Path(source), text="some text")],
        ) as meth:
            self.assertCountEqual(
                self._checkLintFileOnOpen(source),
                [lsp.checkerDiagToLspDict(CheckerDiagnostic(text="some text"))],
            )

            meth.assert_called_once_with(Path(source))

    def runTestBuildSequenceTable(self, tablefmt):
        very_common_pkg = Path(
            p.join(TEST_PROJECT, "basic_library", "very_common_pkg.vhd")
        )
        clk_en_generator = Path(
            p.join(TEST_PROJECT, "basic_library", "clk_en_generator.vhd")
        )

        expected = [
            "Build sequence for %s is" % str(clk_en_generator),
            "",
            tabulate(
                [
                    (1, "basic_library", str(very_common_pkg)),
                    (2, DEFAULT_LIBRARY.name, str(clk_en_generator)),
                ],
                headers=("#", "Library", "Path"),
                tablefmt=tablefmt,
            ),
        ]

        self.assertEqual(
            self.server._getBuildSequenceForHover(clk_en_generator), "\n".join(expected)
        )

    @patch("hdl_checker.lsp.HdlCheckerLanguageServer._use_markdown_for_hover", 0)
    @patch(
        "hdl_checker.builders.base_builder.BaseBuilder.builtin_libraries",
        (Identifier("ieee"),),
    )
    def test_ReportBuildSequencePlain(self):
        self.runTestBuildSequenceTable(tablefmt="plain")

    @patch("hdl_checker.lsp.HdlCheckerLanguageServer._use_markdown_for_hover", 1)
    @patch(
        "hdl_checker.builders.base_builder.BaseBuilder.builtin_libraries",
        (Identifier("ieee"),),
    )
    def test_ReportBuildSequenceMarkdown(self):
        self.runTestBuildSequenceTable(tablefmt="github")

    @patch.object(
        hdl_checker.base_server.BaseServer,
        "resolveDependencyToPath",
        lambda self, _: None,
    )
    def test_DependencyInfoForPathNotFound(self):
        path = Path(p.join(TEST_PROJECT, "another_library", "foo.vhd"))
        dependency = RequiredDesignUnit(
            name=Identifier("clock_divider"),
            library=Identifier("basic_library"),
            owner=path,
            locations=(),
        )
        self.assertEqual(
            self.server._getDependencyInfoForHover(dependency),
            "Couldn't find a source defining 'basic_library.clock_divider'",
        )

    @patch.object(
        hdl_checker.base_server.BaseServer,
        "resolveDependencyToPath",
        lambda self, _: (Path("some_path"), Identifier("some_library")),
    )
    def test_ReportDependencyInfo(self):
        path = Path(p.join(TEST_PROJECT, "another_library", "foo.vhd"))
        dependency = RequiredDesignUnit(
            name=Identifier("clock_divider"),
            library=Identifier("basic_library"),
            owner=path,
            locations=(),
        )
        self.assertEqual(
            self.server._getDependencyInfoForHover(dependency),
            'Path "some_path", library "some_library"',
        )

    def test_ReportDesignUnitAccordingToPosition(self):
        UNIT_A = VhdlDesignUnit(
            owner=Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")),
            type_=DesignUnitType.entity,
            name="unit_a",
            locations=(Location(line=1, column=2), Location(line=3, column=4)),
        )

        UNIT_B = VerilogDesignUnit(
            owner=Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")),
            type_=DesignUnitType.package,
            name="unit_b",
            locations=(Location(line=5, column=6), Location(line=7, column=8)),
        )

        DEP_A = RequiredDesignUnit(
            name=Identifier("dep_a"),
            library=Identifier("lib_a"),
            owner=Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")),
            locations=(Location(line=9, column=10), Location(line=11, column=12)),
        )

        DEP_B = RequiredDesignUnit(
            name=Identifier("dep_a"),
            library=Identifier("lib_a"),
            owner=Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")),
            locations=(Location(line=13, column=14), Location(line=15, column=16)),
        )

        def getDesignUnitsByPath(self, path):  # pylint: disable=unused-argument
            if path != Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")):
                it.fail("Expected foo.vhd but got %s" % path)
            return {UNIT_A, UNIT_B}

        def getDependenciesByPath(self, path):  # pylint: disable=unused-argument
            if path != Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")):
                it.fail("Expected foo.vhd but got %s" % path)
            return {DEP_A, DEP_B}

        patches = (
            patch.object(
                hdl_checker.database.Database,
                "getDesignUnitsByPath",
                getDesignUnitsByPath,
            ),
            patch.object(
                hdl_checker.database.Database,
                "getDependenciesByPath",
                getDependenciesByPath,
            ),
        )

        path = Path(p.join(TEST_PROJECT, "another_library", "foo.vhd"))

        for _patch in patches:
            _patch.start()

        # Check locations outside return nothing
        self.assertIsNone(self.server._getElementAtPosition(path, Location(0, 0)))

        # Check design units are found, ensure boundaries match
        self.assertIsNone(self.server._getElementAtPosition(path, Location(1, 1)))
        self.assertIs(self.server._getElementAtPosition(path, Location(1, 2)), UNIT_A)
        self.assertIs(self.server._getElementAtPosition(path, Location(1, 7)), UNIT_A)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(1, 8)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(3, 3)))
        self.assertIs(self.server._getElementAtPosition(path, Location(3, 4)), UNIT_A)
        self.assertIs(self.server._getElementAtPosition(path, Location(3, 9)), UNIT_A)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(3, 10)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(5, 5)))
        self.assertIs(self.server._getElementAtPosition(path, Location(5, 6)), UNIT_B)
        self.assertIs(self.server._getElementAtPosition(path, Location(5, 11)), UNIT_B)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(5, 12)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(7, 7)))
        self.assertIs(self.server._getElementAtPosition(path, Location(7, 8)), UNIT_B)
        self.assertIs(self.server._getElementAtPosition(path, Location(7, 13)), UNIT_B)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(7, 14)))

        # Now check dependencies
        self.assertIsNone(self.server._getElementAtPosition(path, Location(9, 9)))
        self.assertIs(self.server._getElementAtPosition(path, Location(9, 10)), DEP_A)
        self.assertIs(self.server._getElementAtPosition(path, Location(9, 20)), DEP_A)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(9, 21)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(11, 11)))
        self.assertIs(self.server._getElementAtPosition(path, Location(11, 12)), DEP_A)
        self.assertIs(self.server._getElementAtPosition(path, Location(11, 22)), DEP_A)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(11, 23)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(13, 13)))
        self.assertIs(self.server._getElementAtPosition(path, Location(13, 14)), DEP_B)
        self.assertIs(self.server._getElementAtPosition(path, Location(13, 24)), DEP_B)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(13, 25)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(15, 15)))
        self.assertIs(self.server._getElementAtPosition(path, Location(15, 16)), DEP_B)
        self.assertIs(self.server._getElementAtPosition(path, Location(15, 26)), DEP_B)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(15, 27)))

        for _patch in patches:
            _patch.stop()

    @patch(
        "hdl_checker.builders.base_builder.BaseBuilder.builtin_libraries",
        (Identifier("ieee"),),
    )
    def test_HoverOnInvalidRange(self):
        path = p.join(TEST_PROJECT, "another_library", "foo.vhd")
        self.assertIsNone(
            self.server.hover(uris.from_fs_path(path), {"line": 0, "character": 0})
        )

    @patch(
        "hdl_checker.builders.base_builder.BaseBuilder.builtin_libraries",
        (Identifier("ieee"),),
    )
    def test_HoverOnDesignUnit(self):
        path_to_foo = p.join(TEST_PROJECT, "another_library", "foo.vhd")
        very_common_pkg = p.join(TEST_PROJECT, "basic_library", "very_common_pkg.vhd")
        package_with_constants = p.join(
            TEST_PROJECT, "basic_library", "package_with_constants.vhd"
        )
        clock_divider = p.join(TEST_PROJECT, "basic_library", "clock_divider.vhd")

        expected = [
            "Build sequence for %s is" % str(path_to_foo),
            "",
            tabulate(
                [
                    (1, "basic_library", str(very_common_pkg)),
                    (2, "basic_library", str(package_with_constants)),
                    (3, "basic_library", str(clock_divider)),
                    (4, DEFAULT_LIBRARY.name, str(path_to_foo)),
                ],
                headers=("#", "Library", "Path"),
                tablefmt="plain",
            ),
        ]

        self.assertDictEqual(
            self.server.hover(
                uris.from_fs_path(path_to_foo), {"line": 7, "character": 7}
            ),
            {"contents": "\n".join(expected)},
        )

    @patch(
        "hdl_checker.builders.base_builder.BaseBuilder.builtin_libraries",
        (Identifier("ieee"),),
    )
    def test_HoverOnDependency(self):
        path_to_foo = p.join(TEST_PROJECT, "another_library", "foo.vhd")
        clock_divider = p.join(TEST_PROJECT, "basic_library", "clock_divider.vhd")

        self.assertDictEqual(
            self.server.hover(
                uris.from_fs_path(path_to_foo), {"line": 32, "character": 32}
            ),
            {"contents": 'Path "%s", library "basic_library"' % clock_divider},
        )

    @patch(
        "hdl_checker.builders.base_builder.BaseBuilder.builtin_libraries",
        (Identifier("ieee"),),
    )
    def test_GetDefinitionMatchingDependency(self):
        source = p.join(TEST_PROJECT, "basic_library", "use_entity_a_and_b.vhd")
        target = p.join(TEST_PROJECT, "basic_library", "two_entities_one_file.vhd")

        definitions = self.server.definitions(
            uris.from_fs_path(source), {"line": 1, "character": 9}
        )

        self.assertIn(
            {
                "uri": uris.from_fs_path(target),
                "range": {
                    "start": {"line": 1, "character": 7},
                    "end": {"line": 1, "character": 15},
                },
            },
            definitions,
        )

        self.assertIn(
            {
                "uri": uris.from_fs_path(target),
                "range": {
                    "start": {"line": 4, "character": 7},
                    "end": {"line": 4, "character": 15},
                },
            },
            definitions,
        )

    @patch(
        "hdl_checker.builders.base_builder.BaseBuilder.builtin_libraries",
        (Identifier("ieee"),),
    )
    def test_GetDefinitionBuiltInLibrary(self):
        path_to_foo = p.join(TEST_PROJECT, "another_library", "foo.vhd")

        self.assertEqual(
            self.server.definitions(
                uris.from_fs_path(path_to_foo), {"line": 3, "character": 15}
            ),
            [],
        )

    @patch(
        "hdl_checker.builders.base_builder.BaseBuilder.builtin_libraries",
        (Identifier("ieee"),),
    )
    def test_GetDefinitionNotKnown(self):
        path_to_foo = p.join(TEST_PROJECT, "another_library", "foo.vhd")

        self.assertEqual(
            self.server.definitions(
                uris.from_fs_path(path_to_foo), {"line": 0, "character": 0}
            ),
            [],
        )

    @patch.object(
        hdl_checker.database.Database,
        "getReferencesToDesignUnit",
        return_value=[
            RequiredDesignUnit(
                name=Identifier("clock_divider"),
                library=Identifier("basic_library"),
                owner=Path("some_path"),
                locations=(Location(1, 2), Location(3, 4)),
            )
        ],
    )
    def test_ReferencesOfAValidElement(self, get_references):
        path_to_foo = p.join(TEST_PROJECT, "another_library", "foo.vhd")

        # Make sure we picked up an existing element
        unit = self.server._getElementAtPosition(Path(path_to_foo), Location(7, 7))
        self.assertIsNotNone(unit)

        self.assertCountEqual(
            self.server.references(
                doc_uri=uris.from_fs_path(path_to_foo),
                position={"line": 7, "character": 7},
                exclude_declaration=True,
            ),
            (
                {
                    "uri": uris.from_fs_path("some_path"),
                    "range": {
                        "start": {"line": 1, "character": 2},
                        "end": {"line": 1, "character": 2},
                    },
                },
                {
                    "uri": uris.from_fs_path("some_path"),
                    "range": {
                        "start": {"line": 3, "character": 4},
                        "end": {"line": 3, "character": 4},
                    },
                },
            ),
        )

        get_references.assert_called_once()
        get_references.reset_mock()

        self.assertCountEqual(
            self.server.references(
                doc_uri=uris.from_fs_path(path_to_foo),
                position={"line": 7, "character": 7},
                exclude_declaration=False,
            ),
            (
                {
                    "uri": uris.from_fs_path(path_to_foo),
                    "range": {
                        "start": {"line": 7, "character": 7},
                        "end": {"line": 7, "character": 7},
                    },
                },
                {
                    "uri": uris.from_fs_path("some_path"),
                    "range": {
                        "start": {"line": 1, "character": 2},
                        "end": {"line": 1, "character": 2},
                    },
                },
                {
                    "uri": uris.from_fs_path("some_path"),
                    "range": {
                        "start": {"line": 3, "character": 4},
                        "end": {"line": 3, "character": 4},
                    },
                },
            ),
        )

    def test_ReferencesOfAnInvalidElement(self):
        path_to_foo = p.join(TEST_PROJECT, "another_library", "foo.vhd")

        # Make sure there's no element at this location
        unit = self.server._getElementAtPosition(Path(path_to_foo), Location(0, 0))
        self.assertIsNone(unit)

        for exclude_declaration in (True, False):
            self.assertIsNone(
                self.server.references(
                    doc_uri=uris.from_fs_path(path_to_foo),
                    position={"line": 0, "character": 0},
                    exclude_declaration=exclude_declaration,
                )
            )
Beispiel #20
0
    def test_ReportDesignUnitAccordingToPosition(self):
        UNIT_A = VhdlDesignUnit(
            owner=Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")),
            type_=DesignUnitType.entity,
            name="unit_a",
            locations=(Location(line=1, column=2), Location(line=3, column=4)),
        )

        UNIT_B = VerilogDesignUnit(
            owner=Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")),
            type_=DesignUnitType.package,
            name="unit_b",
            locations=(Location(line=5, column=6), Location(line=7, column=8)),
        )

        DEP_A = RequiredDesignUnit(
            name=Identifier("dep_a"),
            library=Identifier("lib_a"),
            owner=Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")),
            locations=(Location(line=9, column=10), Location(line=11, column=12)),
        )

        DEP_B = RequiredDesignUnit(
            name=Identifier("dep_a"),
            library=Identifier("lib_a"),
            owner=Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")),
            locations=(Location(line=13, column=14), Location(line=15, column=16)),
        )

        def getDesignUnitsByPath(self, path):  # pylint: disable=unused-argument
            if path != Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")):
                it.fail("Expected foo.vhd but got %s" % path)
            return {UNIT_A, UNIT_B}

        def getDependenciesByPath(self, path):  # pylint: disable=unused-argument
            if path != Path(p.join(TEST_PROJECT, "another_library", "foo.vhd")):
                it.fail("Expected foo.vhd but got %s" % path)
            return {DEP_A, DEP_B}

        patches = (
            patch.object(
                hdl_checker.database.Database,
                "getDesignUnitsByPath",
                getDesignUnitsByPath,
            ),
            patch.object(
                hdl_checker.database.Database,
                "getDependenciesByPath",
                getDependenciesByPath,
            ),
        )

        path = Path(p.join(TEST_PROJECT, "another_library", "foo.vhd"))

        for _patch in patches:
            _patch.start()

        # Check locations outside return nothing
        self.assertIsNone(self.server._getElementAtPosition(path, Location(0, 0)))

        # Check design units are found, ensure boundaries match
        self.assertIsNone(self.server._getElementAtPosition(path, Location(1, 1)))
        self.assertIs(self.server._getElementAtPosition(path, Location(1, 2)), UNIT_A)
        self.assertIs(self.server._getElementAtPosition(path, Location(1, 7)), UNIT_A)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(1, 8)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(3, 3)))
        self.assertIs(self.server._getElementAtPosition(path, Location(3, 4)), UNIT_A)
        self.assertIs(self.server._getElementAtPosition(path, Location(3, 9)), UNIT_A)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(3, 10)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(5, 5)))
        self.assertIs(self.server._getElementAtPosition(path, Location(5, 6)), UNIT_B)
        self.assertIs(self.server._getElementAtPosition(path, Location(5, 11)), UNIT_B)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(5, 12)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(7, 7)))
        self.assertIs(self.server._getElementAtPosition(path, Location(7, 8)), UNIT_B)
        self.assertIs(self.server._getElementAtPosition(path, Location(7, 13)), UNIT_B)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(7, 14)))

        # Now check dependencies
        self.assertIsNone(self.server._getElementAtPosition(path, Location(9, 9)))
        self.assertIs(self.server._getElementAtPosition(path, Location(9, 10)), DEP_A)
        self.assertIs(self.server._getElementAtPosition(path, Location(9, 20)), DEP_A)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(9, 21)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(11, 11)))
        self.assertIs(self.server._getElementAtPosition(path, Location(11, 12)), DEP_A)
        self.assertIs(self.server._getElementAtPosition(path, Location(11, 22)), DEP_A)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(11, 23)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(13, 13)))
        self.assertIs(self.server._getElementAtPosition(path, Location(13, 14)), DEP_B)
        self.assertIs(self.server._getElementAtPosition(path, Location(13, 24)), DEP_B)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(13, 25)))

        self.assertIsNone(self.server._getElementAtPosition(path, Location(15, 15)))
        self.assertIs(self.server._getElementAtPosition(path, Location(15, 16)), DEP_B)
        self.assertIs(self.server._getElementAtPosition(path, Location(15, 26)), DEP_B)
        self.assertIsNone(self.server._getElementAtPosition(path, Location(15, 27)))

        for _patch in patches:
            _patch.stop()
Beispiel #21
0
"""
hdl_checker provides a Python API between a VHDL project and some HDL
compilers to catch errors and warnings the compilers generate that can
be used to populate syntax checkers and linters of text editors. It
takes into account the sources dependencies when building so you don't
need to provide a source list ordered by hand.
"""
import os

from ._version import get_versions

from hdl_checker.parsers.elements.identifier import Identifier
from hdl_checker.utils import ON_WINDOWS

__author__ = "Andre Souto ([email protected])"
__license__ = "GPLv3"
__status__ = "Development"

__version__ = get_versions()["version"]
del get_versions

DEFAULT_PROJECT_FILE = os.environ.get(
    "HDL_CHECKER_DEFAULT_PROJECT_FILE",
    "_hdl_checker.config" if ON_WINDOWS else ".hdl_checker.config",
)

CACHE_NAME = os.environ.get("HDL_CHECKER_CACHE_NAME", "cache.json")
WORK_PATH = os.environ.get("HDL_CHECKER_WORK_PATH",
                           "_hdl_checker" if ON_WINDOWS else ".hdl_checker")
DEFAULT_LIBRARY = Identifier("default_library")
Beispiel #22
0
class TestBuilder(TestCase):
    # Create defaults so that pylint doesn't complain about non existing
    # members
    builder_name = None
    builder_path = None

    @classmethod
    def setUpClass(cls):
        setupTestSuport(TEST_TEMP_PATH)

    def setUp(self):
        # type: (...) -> Any
        # Add builder path to the env
        self.original_env = os.environ.copy()

        # Add the builder path to the environment so we can call it
        if self.builder_path:
            _logger.info("Adding '%s' to the system path", self.builder_path)
            self.patch = patch.dict(
                "os.environ",
                {
                    "PATH":
                    os.pathsep.join([self.builder_path, os.environ["PATH"]])
                },
            )
            self.patch.start()

        assert self.builder_name is not None  # To make mypy happy

        builder_class = BUILDER_CLASS_MAP[self.builder_name]
        work_folder = _temp("_%s" % self.builder_name)
        _logger.info("Builder class: %s, work folder is %s", builder_class,
                     work_folder)
        self.builder = builder_class(work_folder,
                                     MagicMock())  # type: AnyBuilder
        self.builder_class = builder_class

    def tearDown(self):
        # type: (...) -> Any
        if self.builder_path:
            self.patch.stop()
        if p.exists("._%s" % self.builder_name):
            shutil.rmtree("._%s" % self.builder_name)

    def test_EnvironmentCheck(self):
        # type: (...) -> Any
        self.builder.checkEnvironment()

    def test_BuilderReportsItsAvailable(self):  # pylint: disable=invalid-name
        # type: (...) -> Any
        self.assertTrue(self.builder_class.isAvailable())  # type: ignore

    def test_CreateLibraryMultipleTimes(self):  # pylint: disable=invalid-name
        # type: (...) -> Any
        self.builder._createLibraryIfNeeded(Identifier("random_lib"))
        self.builder._createLibraryIfNeeded(Identifier("random_lib"))

    def test_BuilderDoesNothingWhenCreatingBuiltinLibraries(self):  # pylint: disable=invalid-name
        # type: (...) -> Any
        self.builder._createLibraryIfNeeded(Identifier("ieee"))

    def test_FindsBuiltinLibraries(self):
        # type: (...) -> Any
        expected = []  # type: List[str]

        if not isinstance(self.builder, Fallback):
            expected += ["ieee", "std"]

        if isinstance(self.builder, MSim):
            expected += ["modelsim_lib"]

        for lib in map(Identifier, expected):
            self.assertIn(lib, self.builder.builtin_libraries)

    @parameterized.parameterized.expand([
        ("/some/file/with/abs/path.vhd", ),
        ("some/file/with/relative/path.vhd", ),
        ("some_file_on_same_level.vhd", ),
        (r"C:\some\file\on\windows.vhd", ),
    ])
    def test_ParseMsimResult(self, path):
        # type: (...) -> Any
        if not isinstance(self.builder, MSim):
            raise unittest2.SkipTest("ModelSim only test")

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    '** Error: %s(21): near "EOF": (vcom-1576) '
                    "expecting ';'." % path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text="near \"EOF\": expecting ';'.",
                    filename=Path(path),
                    line_number=20,
                    error_code="vcom-1576",
                    severity=DiagType.ERROR,
                )
            ],
        )

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "** Warning: %s(23): (vcom-1320) Type of expression "
                    "\"(OTHERS => '0')\" is ambiguous; using element type "
                    "STD_LOGIC_VECTOR, not aggregate type register_type." %
                    path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text="Type of expression \"(OTHERS => '0')\" is "
                    "ambiguous; using element type STD_LOGIC_VECTOR, not "
                    "aggregate type register_type.",
                    filename=Path(path),
                    line_number=22,
                    error_code="vcom-1320",
                    severity=DiagType.WARNING,
                )
            ],
        )

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "** Warning: %s(39): (vcom-1514) Range choice direction "
                    "(downto) does not determine aggregate index range "
                    "direction (to)." % path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text="Range choice direction (downto) does not determine "
                    "aggregate index range direction (to).",
                    filename=Path(path),
                    line_number=38,
                    error_code="vcom-1514",
                    severity=DiagType.WARNING,
                )
            ],
        )

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "** Error: (vcom-11) Could not find work.regfile_pkg.")),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text="Could not find work.regfile_pkg.",
                    error_code="vcom-11",
                    severity=DiagType.ERROR,
                )
            ],
        )

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "** Error (suppressible): %s(7): (vcom-1195) Cannot find "
                    'expanded name "work.regfile_pkg".' % path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text='Cannot find expanded name "work.regfile_pkg".',
                    filename=Path(path),
                    line_number=6,
                    error_code="vcom-1195",
                    severity=DiagType.ERROR,
                )
            ],
        )

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "** Error: %s(7): Unknown expanded name." % path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text="Unknown expanded name.",
                    line_number="6",
                    filename=Path(path),
                    severity=DiagType.ERROR,
                )
            ],
        )

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "** Warning: [14] %s(103): (vcom-1272) Length of expected "
                    "is 4; length of actual is 8." % path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text="Length of expected is 4; length of actual is 8.",
                    line_number="102",
                    error_code="vcom-1272",
                    filename=Path(path),
                    severity=DiagType.WARNING,
                )
            ],
        )

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "** Warning: [14] %s(31): (vcom-1246) Range -1 downto 0 "
                    "is null." % path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text="Range -1 downto 0 is null.",
                    line_number="30",
                    error_code="vcom-1246",
                    filename=Path(path),
                    severity=DiagType.WARNING,
                )
            ],
        )

    @parameterized.parameterized.expand([
        ("/some/file/with/abs/path.vhd", ),
        ("some/file/with/relative/path.vhd", ),
        ("some_file_on_same_level.vhd", ),
        (r"C:\some\file\on\windows.vhd", ),
    ])
    def test_ParseGhdlResult(self, path):
        # type: (...) -> Any
        if not isinstance(self.builder, GHDL):
            raise unittest2.SkipTest("GHDL only test")

        records = list(
            self.builder._makeRecords(
                "%s:11:35: extra ';' at end of interface list" % path))

        expected = [
            BuilderDiag(
                builder_name=self.builder_name,
                filename=Path(path),
                line_number=10,
                column_number=34,
                severity=DiagType.ERROR,
                text="extra ';' at end of interface list",
            )
        ]

        self.assertCountEqual(records, expected)

    @parameterized.parameterized.expand([
        ("/some/file/with/abs/path.vhd", ),
        ("some/file/with/relative/path.vhd", ),
        ("some_file_on_same_level.vhd", ),
    ])
    def test_ParseXvhdlResult(self, path):
        # type: (...) -> Any
        if not isinstance(self.builder, XVHDL):
            raise unittest2.SkipTest("XVHDL only test")

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "ERROR: [VRFC 10-1412] syntax error near ) [%s:12]" %
                    path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text="syntax error near )",
                    filename=Path(path),
                    line_number=11,
                    error_code="VRFC 10-1412",
                    severity=DiagType.ERROR,
                )
            ],
        )

        self.assertEqual(
            list(
                self.builder._makeRecords(
                    "WARNING: [VRFC 10-1256] possible infinite loop; process "
                    "does not have a wait statement [%s:119]" % path)),
            [
                BuilderDiag(
                    builder_name=self.builder_name,
                    text=
                    "possible infinite loop; process does not have a wait statement",
                    filename=Path(path),
                    line_number=118,
                    error_code="VRFC 10-1256",
                    severity=DiagType.WARNING,
                )
            ],
        )

    @patch("hdl_checker.database.Database.getLibrary",
           return_value=Identifier("work"))
    def test_VhdlCompilation(self, *args):
        # type: (...) -> Any
        if FileType.vhdl not in self.builder.file_types:
            raise unittest2.SkipTest("Builder {} doesn't support VHDL".format(
                self.builder_name))

        source = _source("no_messages.vhd")
        records, rebuilds = self.builder.build(source, Identifier("work"),
                                               BuildFlagScope.single)
        self.assertNotIn(
            DiagType.ERROR,
            [x.severity for x in records],
            "This source should not generate errors.",
        )
        self.assertFalse(rebuilds)

    @patch("hdl_checker.database.Database.getLibrary",
           return_value=Identifier("work"))
    def test_VerilogCompilation(self, *args):
        # type: (...) -> Any
        if FileType.verilog not in self.builder.file_types:
            raise unittest2.SkipTest(
                "Builder {} doesn't support Verilog".format(self.builder_name))

        source = _source("no_messages.v")

        records, rebuilds = self.builder.build(source, Identifier("work"),
                                               BuildFlagScope.single)

        self.assertNotIn(
            DiagType.ERROR,
            [x.severity for x in records],
            "This source should not generate errors.",
        )
        self.assertFalse(rebuilds)

    @patch("hdl_checker.database.Database.getLibrary",
           return_value=Identifier("work"))
    def test_SystemverilogCompilation(self, *args):
        # type: (...) -> Any
        if FileType.systemverilog not in self.builder.file_types:
            raise unittest2.SkipTest(
                "Builder {} doesn't support SystemVerilog".format(
                    self.builder_name))

        source = _source("no_messages.sv")

        records, rebuilds = self.builder.build(source, Identifier("work"),
                                               BuildFlagScope.single)

        self.assertNotIn(
            DiagType.ERROR,
            [x.severity for x in records],
            "This source should not generate errors.",
        )
        self.assertFalse(rebuilds)

    def test_CatchAKnownError(self):
        # type: (...) -> Any
        source = _source("source_with_error.vhd")

        records, rebuilds = self.builder.build(source,
                                               Identifier("lib"),
                                               forced=True,
                                               scope=BuildFlagScope.single)

        for record in records:
            _logger.info(record)

        if self.builder_name == "msim":
            expected = [{
                BuilderDiag(
                    filename=source,
                    builder_name=self.builder_name,
                    text='Unknown identifier "some_lib".',
                    line_number=3,
                    error_code="vcom-1136",
                    severity=DiagType.ERROR,
                )
            }]
        elif self.builder_name == "ghdl":
            expected = [{
                BuilderDiag(
                    filename=source,
                    builder_name=self.builder_name,
                    text='no declaration for "some_lib"',
                    line_number=3,
                    column_number=4,
                    severity=DiagType.ERROR,
                ),
                BuilderDiag(
                    filename=source,
                    builder_name=self.builder_name,
                    text="entity 'source_with_error' was not analysed",
                    line_number=17,
                    column_number=13,
                    severity=DiagType.ERROR,
                ),
            }]
        elif self.builder_name == "xvhdl":
            # XVHDL reports different errors depending on the version
            expected = [
                {
                    BuilderDiag(
                        filename=source,
                        builder_name=self.builder_name,
                        text="some_lib is not declared",
                        line_number=3,
                        error_code="VRFC 10-91",
                        severity=DiagType.ERROR,
                    )
                },
                {
                    BuilderDiag(
                        filename=source,
                        builder_name=self.builder_name,
                        text="'some_lib' is not declared",
                        line_number=3,
                        error_code="VRFC 10-2989",
                        severity=DiagType.ERROR,
                    )
                },
            ]

        if not isinstance(self.builder, Fallback):
            self.assertIn(records, expected)
        else:
            self.assertFalse(records)

        self.assertFalse(rebuilds)

    def test_MsimRecompileMsg0(self):
        # type: (...) -> Any
        if not isinstance(self.builder, MSim):
            raise unittest2.SkipTest("ModelSim only test")

        line = ("** Error: (vcom-13) Recompile foo_lib.bar_component because "
                "foo_lib.foo_lib_pkg has changed.")

        self.assertEqual(
            [{
                "library_name": "foo_lib",
                "unit_name": "bar_component"
            }],
            self.builder._searchForRebuilds(line),
        )

    def test_MsimRecompileMsg1(self):
        # type: (...) -> Any
        if not isinstance(self.builder, MSim):
            raise unittest2.SkipTest("ModelSim only test")

        line = (
            "** Error: (vcom-13) Recompile foo_lib.bar_component because "
            "foo_lib.foo_lib_pkg, base_library.very_common_package have changed."
        )

        self.assertEqual(
            [{
                "library_name": "foo_lib",
                "unit_name": "bar_component"
            }],
            self.builder._searchForRebuilds(line),
        )

    def test_GhdlRecompileMsg(self):
        # type: (...) -> Any
        if not isinstance(self.builder, GHDL):
            raise unittest2.SkipTest("GHDL only test")

        line = 'somefile.vhd:12:13: package "leon3" is obsoleted by package "amba"'

        self.assertEqual(
            [{
                "unit_type": "package",
                "unit_name": "leon3"
            }],
            self.builder._searchForRebuilds(line),
        )

    def test_XvhdlRecompileMsg0(self):
        # type: (...) -> Any
        if not isinstance(self.builder, XVHDL):
            raise unittest2.SkipTest("XVHDL only test")

        line = (
            "ERROR: [VRFC 10-113] {} needs to be re-saved since std.standard "
            "changed".format(
                p.join("some", "path", "xsim.dir", "some_library",
                       "some_package.vdb")))

        self.assertEqual(
            [{
                "library_name": "some_library",
                "unit_name": "some_package"
            }],
            self.builder._searchForRebuilds(line),
        )

    # Rebuild formats are:
    # - {unit_type: '', 'unit_name': }
    # - {library_name: '', 'unit_name': }
    # - {rebuild_path: ''}
    @parameterized.parameterized.expand([
        (
            {
                "unit_type": "package",
                "unit_name": "very_common_pkg"
            },
            RebuildUnit(name=Identifier("very_common_pkg"),
                        type_=DesignUnitType.package),
        ),
        # Should replace 'work' with the path's library
        (
            {
                "library_name": "work",
                "unit_name": "foo"
            },
            RebuildLibraryUnit(name=Identifier("foo"),
                               library=Identifier("some_lib")),
        ),
        # Should not touch the library name when != 'work'
        (
            {
                "library_name": "foo",
                "unit_name": "bar"
            },
            RebuildLibraryUnit(name=Identifier("bar"),
                               library=Identifier("foo")),
        ),
        ({
            "rebuild_path": "some_path"
        }, RebuildPath(Path("some_path"))),
    ])
    def test_GetRebuilds(self, rebuild_info, expected):
        # type: (...) -> Any
        _logger.info("Rebuild info is %s", rebuild_info)
        library = Identifier("some_lib", False)
        with patch.object(self.builder,
                          "_searchForRebuilds",
                          return_value=[rebuild_info]):
            self.builder._database.getDependenciesByPath = MagicMock(
                return_value=[
                    RequiredDesignUnit(
                        owner=Path(""),
                        name=Identifier("very_common_pkg"),
                        library=Identifier("work"),
                    )
                ])

            self.assertCountEqual(
                self.builder._getRebuilds(_source("source.vhd"), "", library),
                {expected},
            )
Beispiel #23
0
        open(source, "w").write("")

        project = DummyServer(_Path(path))
        project.setConfig(Path(config))
        # Get messages of anything to trigger reading the config
        project.getMessagesByPath(Path(source))

        handle_ui_info.assert_called_once_with("No sources were added")

        removeIfExists(path)

    @it.should("warn when unable to resolve non-builtin dependencies"
               )  # type: ignore
    @patch(
        "hdl_checker.builders.fallback.Fallback._parseBuiltinLibraries",
        return_value=[Identifier("builtin")],
    )
    def test(parse_builtins):
        # type: (...) -> None
        root = tempfile.mkdtemp()
        server = DummyServer(Path(root))

        with tempfile.NamedTemporaryFile(suffix=".vhd") as filename:
            diags = server.getMessagesWithText(
                Path(filename.name),
                "library lib; use lib.pkg.all; library builtin; use builtin.foo;",
            )

            parse_builtins.assert_called()

            logIterable("Diags", diags, _logger.info)
Beispiel #24
0
 def includedPath(name):
     return IncludedPath(
         name=Identifier(name),
         owner=Path("owner"),
         locations=frozenset([Location(0, 0)]),
     )
Beispiel #25
0
 def requiredDesignUnit(name):
     return RequiredDesignUnit(
         name=Identifier(name),
         owner=Path("owner"),
         locations=frozenset([Location(0, 0)]),
     )
Beispiel #26
0
    def test_IncludedPaths(self, filetype):
        # type: (...) -> Any
        work_folder = mkdtemp()
        database = MagicMock(spec=Database)

        def includedPath(name):
            return IncludedPath(
                name=Identifier(name),
                owner=Path("owner"),
                locations=frozenset([Location(0, 0)]),
            )

        def requiredDesignUnit(name):
            return RequiredDesignUnit(
                name=Identifier(name),
                owner=Path("owner"),
                locations=frozenset([Location(0, 0)]),
            )

        included_results = Queue()  # type: Queue[Optional[Path]]
        included_results.put(Path(p.join("", "library", "some", "")))
        included_results.put(None)

        def resolveIncludedPath(*_):
            return included_results.get(block=False)

        database.getDependenciesByPath.return_value = [
            includedPath(name="resolved/include"),
            includedPath(name="unresolved/include"),
            requiredDesignUnit(name="some_unit"),
        ]

        database.resolveIncludedPath = resolveIncludedPath

        calls = []  # type: List[List[str]]

        def shell(cmd_with_args, *args, **kwargs):
            calls.append(cmd_with_args)
            _logger.debug("$ %s", cmd_with_args)
            if "-version" in cmd_with_args:
                return ("vcom 10.2c Compiler 2013.07 Jul 18 2013", )
            return ("", )

        if filetype is FileType.verilog:
            source = _source("no_messages.v")
        else:
            source = _source("no_messages.sv")

        with patch("hdl_checker.builders.msim.runShellCommand", shell):
            builder = MSim(Path(work_folder), database=database)

            records, rebuilds = builder.build(source, Identifier("work"),
                                              BuildFlagScope.single)

        expected = [
            "vlog",
            "-modelsimini",
            p.join(work_folder, "modelsim.ini"),
            "-quiet",
            "-work",
            p.join(work_folder, "work"),
        ]

        if filetype is FileType.systemverilog:
            expected += ["-sv"]

        expected += [
            "-lint",
            "-hazards",
            "-pedanticerrors",
            "-L",
            "work",
            "+incdir+" + p.join("", "library", "some"),
            str(source),
        ]

        self.assertEqual(expected, calls[-1])

        self.assertFalse(records)
        self.assertFalse(rebuilds)
Beispiel #27
0
 def _RebuildLibraryUnit(name, library):
     return RebuildLibraryUnit(name=Identifier(name),
                               library=Identifier(library))
Beispiel #28
0
    def test_CatchAKnownError(self):
        # type: (...) -> Any
        source = _source("source_with_error.vhd")

        records, rebuilds = self.builder.build(source,
                                               Identifier("lib"),
                                               forced=True,
                                               scope=BuildFlagScope.single)

        for record in records:
            _logger.info(record)

        if self.builder_name == "msim":
            expected = [{
                BuilderDiag(
                    filename=source,
                    builder_name=self.builder_name,
                    text='Unknown identifier "some_lib".',
                    line_number=3,
                    error_code="vcom-1136",
                    severity=DiagType.ERROR,
                )
            }]
        elif self.builder_name == "ghdl":
            expected = [{
                BuilderDiag(
                    filename=source,
                    builder_name=self.builder_name,
                    text='no declaration for "some_lib"',
                    line_number=3,
                    column_number=4,
                    severity=DiagType.ERROR,
                ),
                BuilderDiag(
                    filename=source,
                    builder_name=self.builder_name,
                    text="entity 'source_with_error' was not analysed",
                    line_number=17,
                    column_number=13,
                    severity=DiagType.ERROR,
                ),
            }]
        elif self.builder_name == "xvhdl":
            # XVHDL reports different errors depending on the version
            expected = [
                {
                    BuilderDiag(
                        filename=source,
                        builder_name=self.builder_name,
                        text="some_lib is not declared",
                        line_number=3,
                        error_code="VRFC 10-91",
                        severity=DiagType.ERROR,
                    )
                },
                {
                    BuilderDiag(
                        filename=source,
                        builder_name=self.builder_name,
                        text="'some_lib' is not declared",
                        line_number=3,
                        error_code="VRFC 10-2989",
                        severity=DiagType.ERROR,
                    )
                },
            ]

        if not isinstance(self.builder, Fallback):
            self.assertIn(records, expected)
        else:
            self.assertFalse(records)

        self.assertFalse(rebuilds)
Beispiel #29
0
 def _RebuildUnit(name, type_):
     return RebuildUnit(name=Identifier(name), type_=Identifier(type_))
Beispiel #30
0
 def test_BuilderDoesNothingWhenCreatingBuiltinLibraries(self):  # pylint: disable=invalid-name
     # type: (...) -> Any
     self.builder._createLibraryIfNeeded(Identifier("ieee"))