For many years I made a living working on static analysis tools and that included a lot of compiler construction stuff. Unfortunately not all languages are equally amenable to static analysis.
Take C++ for example. On one hand C++ is statically typed and that helps in static analysis and refactoring. On the other hand, its semantic is so horribly complicated that it makes almost impossible to write static analyzers for it and useful refactoring tools for C++ are almost non-existent. Pointer aliasing and macroprocessor just add insult to injury.
Python on the other hand is very clean language, no macroprocessor, but it is dynamically typed which makes reasoning about code very difficult.
Java (and after it, C#) managed to strike very nice balance, that is why tooling ecosystems for these languages are very good. The road to good tools starts with carefully designed language.