Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Language Server #11350

Merged
merged 1 commit into from
Dec 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,19 @@ defaults:
- store_artifacts: *artifacts_test_results
- gitter_notify_failure_unless_pr

- steps_test_lsp: &steps_test_lsp
steps:
- checkout
- attach_workspace:
at: build
- run:
name: Install dependencies
command: pip install --user deepdiff colorama
- run:
name: Executing solc LSP test suite
command: ./test/lsp.py ./build/solc/solc
- gitter_notify_failure_unless_pr

- steps_soltest_all: &steps_soltest_all
steps:
- checkout
Expand Down Expand Up @@ -519,7 +532,7 @@ jobs:
command: apt -q update && apt install -y python3-pip
- run:
name: Install pylint
command: python3 -m pip install pylint z3-solver pygments-lexer-solidity parsec tabulate
command: python3 -m pip install pylint z3-solver pygments-lexer-solidity parsec tabulate deepdiff colorama
# also z3-solver, parsec and tabulate to make sure pylint knows about this module, pygments-lexer-solidity for docs
- run:
name: Linting Python Scripts
Expand Down Expand Up @@ -887,6 +900,10 @@ jobs:
parallelism: 15 # 7 EVM versions, each with/without optimization + 1 ABIv1/@nooptions run
<<: *steps_soltest_all

t_ubu_lsp: &t_ubu_lsp
<<: *base_ubuntu2004_small
<<: *steps_test_lsp

t_archlinux_soltest: &t_archlinux_soltest
<<: *base_archlinux
environment:
Expand Down Expand Up @@ -1288,6 +1305,7 @@ workflows:
- t_ubu_soltest_enforce_yul: *workflow_ubuntu2004
- b_ubu_clang: *workflow_trigger_on_tags
- t_ubu_clang_soltest: *workflow_ubuntu2004_clang
- t_ubu_lsp: *workflow_ubuntu2004

# Ubuntu fake release build and tests
- b_ubu_release: *workflow_trigger_on_tags
Expand Down
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Language Features:


Compiler Features:
* Commandline Interface: Add ``--lsp`` option to get ``solc`` to act as a Language Server (LSP) communicating over stdio.


Bugfixes:
Expand Down
6 changes: 6 additions & 0 deletions libsolidity/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ set(sources
interface/StorageLayout.h
interface/Version.cpp
interface/Version.h
lsp/LanguageServer.cpp
lsp/LanguageServer.h
lsp/FileRepository.cpp
lsp/FileRepository.h
lsp/Transport.cpp
lsp/Transport.h
parsing/DocStringParser.cpp
parsing/DocStringParser.h
parsing/Parser.cpp
Expand Down
64 changes: 64 additions & 0 deletions libsolidity/lsp/FileRepository.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
This file is part of solidity.

solidity 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 3 of the License, or
(at your option) any later version.

solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-3.0

#include <libsolidity/lsp/FileRepository.h>

using namespace std;
using namespace solidity;
using namespace solidity::lsp;

namespace
{

string stripFilePrefix(string const& _path)
{
if (_path.find("file://") == 0)
return _path.substr(7);
else
return _path;
}

}

string FileRepository::sourceUnitNameToClientPath(string const& _sourceUnitName) const
{
if (m_sourceUnitNamesToClientPaths.count(_sourceUnitName))
return m_sourceUnitNamesToClientPaths.at(_sourceUnitName);
else if (_sourceUnitName.find("file://") == 0)
return _sourceUnitName;
else
return "file://" + (m_fileReader.basePath() / _sourceUnitName).generic_string();
}

string FileRepository::clientPathToSourceUnitName(string const& _path) const
{
return m_fileReader.cliPathToSourceUnitName(stripFilePrefix(_path));
}

map<string, string> const& FileRepository::sourceUnits() const
{
return m_fileReader.sourceUnits();
}

void FileRepository::setSourceByClientPath(string const& _uri, string _text)
{
// This is needed for uris outside the base path. It can lead to collisions,
// but we need to mostly rewrite this in a future version anyway.
m_sourceUnitNamesToClientPaths.emplace(clientPathToSourceUnitName(_uri), _uri);
m_fileReader.addOrUpdateFile(stripFilePrefix(_uri), move(_text));
}
53 changes: 53 additions & 0 deletions libsolidity/lsp/FileRepository.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
This file is part of solidity.

solidity 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 3 of the License, or
(at your option) any later version.

solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-3.0
#pragma once

#include <libsolidity/interface/FileReader.h>

#include <string>
#include <map>

namespace solidity::lsp
{

class FileRepository
{
public:
explicit FileRepository(boost::filesystem::path const& _basePath):
m_fileReader(_basePath) {}

boost::filesystem::path const& basePath() const { return m_fileReader.basePath(); }

/// Translates a compiler-internal source unit name to an LSP client path.
std::string sourceUnitNameToClientPath(std::string const& _sourceUnitName) const;
/// Translates an LSP client path into a compiler-internal source unit name.
std::string clientPathToSourceUnitName(std::string const& _uri) const;

/// @returns all sources by their compiler-internal source unit name.
std::map<std::string, std::string> const& sourceUnits() const;
/// Changes the source identified by the LSP client path _uri to _text.
void setSourceByClientPath(std::string const& _uri, std::string _text);

frontend::ReadCallback::Callback reader() { return m_fileReader.reader(); }

private:
std::map<std::string, std::string> m_sourceUnitNamesToClientPaths;
frontend::FileReader m_fileReader;
};

}
Loading