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

Omnisharp roslyn #213

Closed
wants to merge 2 commits into from
Closed
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ doc/tags
# Exclude tern installation area
third_party/tern_runtime/node_modules

# Exclude omnisharp-roslyn installation area
third_party/omnisharp-roslyn/

# Exclude vagrant directory
.vagrant/

Expand Down
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "third_party/OmniSharpServer"]
path = third_party/OmniSharpServer
url = https://github.com/nosami/OmniSharpServer
[submodule "third_party/argparse"]
path = third_party/argparse
url = https://github.com/bewest/argparse
Expand Down
81 changes: 75 additions & 6 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def OnMac():
def OnWindows():
return platform.system() == 'Windows'

def OnCygwin():
return platform.system().startswith("CYGWIN")


def OnTravisOrAppVeyor():
return 'CI' in os.environ
Expand Down Expand Up @@ -411,13 +414,79 @@ def BuildYcmdLib( args ):


def BuildOmniSharp():
build_command = PathToFirstExistingExecutable(
[ 'msbuild', 'msbuild.exe', 'xbuild' ] )
if not build_command:
sys.exit( 'ERROR: msbuild or xbuild is required to build Omnisharp.' )
build_dir = p.join( DIR_OF_THIRD_PARTY, "omnisharp-roslyn" )
try:
try:
os.mkdir( build_dir )
except OSError:
pass
os.chdir( build_dir )
version = "v1.9-beta20"
url_pattern = ( "https://github.com/OmniSharp/omnisharp-roslyn/"
"releases/download/{0}/{1}" )
if OnWindows() or OnCygwin():
if platform.machine().endswith( '64' ):
url_file = 'omnisharp-win-x64-netcoreapp1.0.zip'
else:
url_file = 'omnisharp-win-x86-netcoreapp1.0.zip'
elif OnMac():
url_file = 'omnisharp-osx-x64-netcoreapp1.0.tar.gz'
else:
disto_package_names = {
'Centos': 'omnisharp-centos-x64-netcoreapp1.0.tar.gz',
'debian': 'omnisharp-debian-x64-netcoreapp1.0.tar.gz',
'rhel': 'omnisharp-rhel-x64-netcoreapp1.0.tar.gz',
'Ubuntu': 'omnisharp-ubuntu-x64-netcoreapp1.0.tar.gz'
}
supported_dists = disto_package_names.keys()
disto = platform.linux_distribution( supported_dists = supported_dists,
full_distribution_name = False )[ 0 ]
try:
url_file = disto_package_names[ disto ]
except KeyValue:
url_file = 'omnisharp-linux-x64-netcoreapp1.0.tar.gz'

try:
os.mkdir( version )
except OSError:
pass

file_path = p.join( version, url_file )
if not p.exists( file_path ):
sys.path.insert( 1, p.abspath( p.join( DIR_OF_THIRD_PARTY,
'requests' ) ) )
import requests
result = requests.get( url_pattern.format( version, url_file ) )
with open( file_path, 'wb' ) as fh:
fh.write( result.content )

if OnCygwin():
extract_command = [ 'unzip', file_path ]
elif OnWindows():
try:
import _winreg
except ImportError:
import winreg as _winreg

wow64 = _winreg.KEY_READ | _winreg.KEY_WOW64_64KEY
with _winreg.ConnectRegistry( None, _winreg.HKEY_LOCAL_MACHINE ) as LM:
with _winreg.OpenKey( LM, 'SOFTWARE', 0, wow64 ) as S:
with _winreg.OpenKey( S, '7-Zip', 0, wow64 ) as SZ:
seven_zip_path = _winreg.QueryValueEx( SZ, 'Path' )[ 0 ]

extract_command = [ p.join( seven_zip_path, '7z.exe' ), '-y', 'x', file_path ]
else:
extract_command = [ 'tar', 'xfv', file_path ]

subprocess.check_call( extract_command )

os.chdir( p.join( DIR_OF_THIS_SCRIPT, 'third_party', 'OmniSharpServer' ) )
CheckCall( [ build_command, '/property:Configuration=Release' ] )
if OnCygwin():
import glob
exes = glob.glob( '*.exe' )
dlls = glob.glob( '*.dll' )
subprocess.check_call( [ "chmod", "a+x" ] + exes + dlls )
finally:
os.chdir( DIR_OF_THIS_SCRIPT )


def BuildGoCode():
Expand Down
1 change: 0 additions & 1 deletion third_party/OmniSharpServer
Submodule OmniSharpServer deleted from e19029
36 changes: 19 additions & 17 deletions ycmd/completers/cs/cs_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@
'"./install.py --omnisharp-completer".' )
INVALID_FILE_MESSAGE = 'File is invalid.'
NO_DIAGNOSTIC_MESSAGE = 'No diagnostic for current line!'
OMNISHARP_BINARY = ( 'OmniSharp.exe' if utils.OnWindows() or utils.OnCygwin()
else 'OmniSharp' )
PATH_TO_OMNISHARP_BINARY = os.path.abspath(
os.path.join( os.path.dirname( __file__ ), '..', '..', '..',
'third_party', 'OmniSharpServer', 'OmniSharp',
'bin', 'Release', 'OmniSharp.exe' ) )
'third_party', 'omnisharp-roslyn', OMNISHARP_BINARY ) )
LOGFILE_FORMAT = 'omnisharp_{port}_{sln}_{std}_'


Expand Down Expand Up @@ -384,12 +385,6 @@ def _StartServer( self ):
'-s',
u'{0}'.format( path_to_solutionfile ) ]

if not utils.OnWindows() and not utils.OnCygwin():
command.insert( 0, 'mono' )

if utils.OnCygwin():
command.extend( [ '--client-path-mode', 'Cygwin' ] )

solutionfile = os.path.basename( path_to_solutionfile )
self._filename_stdout = utils.CreateLogfile(
LOGFILE_FORMAT.format( port = self._omnisharp_port,
Expand All @@ -414,7 +409,7 @@ def _StopServer( self ):
if self._ServerIsRunning():
self._logger.info( 'Stopping OmniSharp server with PID {0}'.format(
self._omnisharp_phandle.pid ) )
self._GetResponse( '/stopserver' )
self._GetResponse( '/stopserver', returns_json = False )
try:
utils.WaitUntilProcessIsTerminated( self._omnisharp_phandle,
timeout = 5 )
Expand Down Expand Up @@ -447,7 +442,8 @@ def _RestartServer( self ):
def _ReloadSolution( self ):
""" Reloads the solutions in the OmniSharp server """
self._logger.info( 'Reloading Solution in OmniSharp server' )
return self._GetResponse( '/reloadsolution' )
self._GetResponse( '/reloadsolution', returns_json = False )
return True


def CompletionType( self, request_data ):
Expand Down Expand Up @@ -550,13 +546,13 @@ def _GetDoc( self, request_data ):
def _DefaultParameters( self, request_data ):
""" Some very common request parameters """
parameters = {}
parameters[ 'line' ] = request_data[ 'line_num' ]
parameters[ 'column' ] = request_data[ 'column_codepoint' ]
parameters[ 'Line' ] = request_data[ 'line_num' ]
parameters[ 'Column' ] = request_data[ 'column_codepoint' ]

filepath = request_data[ 'filepath' ]
parameters[ 'buffer' ] = (
parameters[ 'Buffer' ] = (
request_data[ 'file_data' ][ filepath ][ 'contents' ] )
parameters[ 'filename' ] = filepath
parameters[ 'FileName' ] = filepath
return parameters


Expand Down Expand Up @@ -598,11 +594,17 @@ def _ServerLocation( self ):
return 'http://localhost:' + str( self._omnisharp_port )


def _GetResponse( self, handler, parameters = {}, timeout = None ):
def _GetResponse( self, handler, parameters = {}, timeout = None,
returns_json = True ):
""" Handle communication with server """
target = urllib.parse.urljoin( self._ServerLocation(), handler )
response = requests.post( target, data = parameters, timeout = timeout )
return response.json()
self._logger.info( "Request: " + str(parameters) )
response = requests.post( target, json = parameters, timeout = timeout )
self._logger.info( "Response: " + response.text )
if returns_json:
return response.json()
else:
return None


def _ChooseOmnisharpPort( self ):
Expand Down
105 changes: 52 additions & 53 deletions ycmd/tests/cs/diagnostics_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
standard_library.install_aliases()
from builtins import * # noqa

from hamcrest import ( assert_that, contains, contains_string, equal_to,
from hamcrest import ( assert_that, has_items, contains_string, equal_to,
has_entries, has_entry )

from ycmd.tests.cs import PathToTestFile, SharedYcmd, WrapOmniSharpServer
Expand Down Expand Up @@ -54,7 +54,7 @@ def Diagnostics_Basic_test( app ):
has_entry(
'message',
contains_string(
"Unexpected symbol `}'', expecting identifier" ) ) )
"'Console' does not contain a definition for ''" ) ) )


@SharedYcmd
Expand All @@ -73,64 +73,64 @@ def Diagnostics_ZeroBasedLineAndColumn_test( app ):
results = app.post_json( '/event_notification', event_data ).json

assert_that( results,
contains(
has_items(
has_entries( {
'kind': equal_to( 'ERROR' ),
'text': contains_string(
"Unexpected symbol `}'', expecting identifier" ),
"Identifier expected" ),
'location': has_entries( {
'line_num': 11,
'column_num': 2
'line_num': 10,
'column_num': 12
} ),
'location_extent': has_entries( {
'start': has_entries( {
'line_num': 11,
'column_num': 2,
'line_num': 10,
'column_num': 12,
} ),
'end': has_entries( {
'line_num': 11,
'column_num': 2,
'line_num': 10,
'column_num': 12,
} ),
} )
} ) ) )


@SharedYcmd
def Diagnostics_WithRange_test( app ):
filepath = PathToTestFile( 'testy', 'DiagnosticRange.cs' )
with WrapOmniSharpServer( app, filepath ):
contents = ReadFile( filepath )

results = {}
for _ in ( 0, 1 ): # First call always returns blank for some reason
event_data = BuildRequest( filepath = filepath,
event_name = 'FileReadyToParse',
filetype = 'cs',
contents = contents )

results = app.post_json( '/event_notification', event_data ).json

assert_that( results,
contains(
has_entries( {
'kind': equal_to( 'WARNING' ),
'text': contains_string(
"Name should have prefix '_'" ),
'location': has_entries( {
'line_num': 3,
'column_num': 16
} ),
'location_extent': has_entries( {
'start': has_entries( {
'line_num': 3,
'column_num': 16,
} ),
'end': has_entries( {
'line_num': 3,
'column_num': 25,
} ),
} )
} ) ) )
# @SharedYcmd
# def Diagnostics_WithRange_test( app ):
# filepath = PathToTestFile( 'testy', 'DiagnosticRange.cs' )
# with WrapOmniSharpServer( app, filepath ):
# contents = ReadFile( filepath )
#
# results = {}
# for _ in ( 0, 1 ): # First call always returns blank for some reason
# event_data = BuildRequest( filepath = filepath,
# event_name = 'FileReadyToParse',
# filetype = 'cs',
# contents = contents )
#
# results = app.post_json( '/event_notification', event_data ).json
#
# assert_that( results,
# contains(
# has_entries( {
# 'kind': equal_to( 'WARNING' ),
# 'text': contains_string(
# "Name should have prefix '_'" ),
# 'location': has_entries( {
# 'line_num': 3,
# 'column_num': 16
# } ),
# 'location_extent': has_entries( {
# 'start': has_entries( {
# 'line_num': 3,
# 'column_num': 16,
# } ),
# 'end': has_entries( {
# 'line_num': 3,
# 'column_num': 25,
# } ),
# } )
# } ) ) )


@SharedYcmd
Expand All @@ -139,7 +139,7 @@ def Diagnostics_MultipleSolution_test( app ):
PathToTestFile( 'testy-multiple-solutions',
'solution-named-like-folder',
'testy', 'Program.cs' ) ]
lines = [ 11, 10 ]
lines = [ 10, 9 ]
for filepath, line in zip( filepaths, lines ):
with WrapOmniSharpServer( app, filepath ):
contents = ReadFile( filepath )
Expand All @@ -154,23 +154,22 @@ def Diagnostics_MultipleSolution_test( app ):
results = app.post_json( '/event_notification', event_data ).json

assert_that( results,
contains(
has_items(
has_entries( {
'kind': equal_to( 'ERROR' ),
'text': contains_string( "Unexpected symbol `}'', "
"expecting identifier" ),
'text': contains_string( "Identifier expected" ),
'location': has_entries( {
'line_num': line,
'column_num': 2
'column_num': 12
} ),
'location_extent': has_entries( {
'start': has_entries( {
'line_num': line,
'column_num': 2,
'column_num': 12,
} ),
'end': has_entries( {
'line_num': line,
'column_num': 2,
'column_num': 12,
} ),
} )
} ) ) )
Loading