// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT License. See LICENSE file in the project root for license information.
package com.microsoft.javapkgsrv;
import java.io.IOException;
import java.util.List;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;
import com.microsoft.javapkgsrv.Protocol.FileIdentifier;
import com.microsoft.javapkgsrv.Protocol.Request.RequestType;
import com.microsoft.javapkgsrv.Protocol.Response.AddTypeRootResponse;
import com.microsoft.javapkgsrv.Protocol.Response.AutocompleteResponse.Completion;
import com.microsoft.javapkgsrv.Protocol.Response.AutocompleteResponse;
import com.microsoft.javapkgsrv.Protocol.Response.FileParseMessagesResponse;
import com.microsoft.javapkgsrv.Protocol.Response.FileParseMessagesResponse.Problem;
import com.microsoft.javapkgsrv.Protocol.Response.FileParseResponse;
import com.microsoft.javapkgsrv.Protocol.Response.FindDefinitionResponse;
import com.microsoft.javapkgsrv.Protocol.Response.OpenTypeRootResponse;
import com.microsoft.javapkgsrv.Protocol.Response.OutlineResultResponse;
import com.microsoft.javapkgsrv.Protocol.Response.OutlineResultResponse.Outline;
import com.microsoft.javapkgsrv.Protocol.Response.ParamHelpPositionUpdateResponse;
import com.microsoft.javapkgsrv.Protocol.Response.ParamHelpResponse;
import com.microsoft.javapkgsrv.Protocol.Response.ParamHelpResponse.Signature;
import com.microsoft.javapkgsrv.Protocol.Response.QuickInfoResponse;
import com.microsoft.javapkgsrv.Protocol.Response.QuickInfoResponse.JavaElement;
import com.microsoft.javapkgsrv.Protocol.Response.ResponseType;
import com.microsoft.javapkgsrv.Protocol.TypeRootIdentifier;
public class ClientProxy {
private PipeChannel Pipe = null;
private JavaParser Parser = new JavaParser();
public ClientProxy()
{
Pipe = new PipeChannel();
}
public ClientProxy(String pipeName)
{
Pipe = new PipeChannel(pipeName);
}
public void Run() throws IOException, JavaModelException
{
Pipe.Init();
Parser.Init();
while (true)
{
try
{
Protocol.Request request = Pipe.ReadMessage();
Protocol.Response response = ProcessRequest(request);
Pipe.WriteMessage(response);
if (request.getRequestType().equals(RequestType.Bye))
break; // return to allow the process to exit
}
catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
private Protocol.Response ProcessRequest(Protocol.Request request)
{
if (request.getRequestType().equals(RequestType.FileParse))
{
try
{
System.out.print("Parsing " + request.getFileParseRequest().getFileName());
Integer result = Parser.ProcessParseRequest(
request.getFileParseRequest().getFileParseContents(),
request.getFileParseRequest().getFileName());
System.out.println(" id = " + result.toString());
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.FileParseStatus)
.setFileParseResponse(FileParseResponse.newBuilder()
.setStatus(true)
.setFileIdentifier(FileIdentifier.newBuilder()
.setId(result)
.build())
.build())
.build();
}
catch(Exception e)
{
e.printStackTrace();
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.FileParseStatus)
.setFileParseResponse(FileParseResponse.newBuilder()
.setStatus(false)
.setErrorMessage(e.getMessage() != null ? e.getMessage() : e.toString())
.build())
.build();
}
}
else if (request.getRequestType().equals(RequestType.DisposeFile))
{
Integer fileId = request.getDisposeFileRequest().getFileIdentifier().getId();
System.out.println("Remove AST for id = " + fileId);
Parser.ProcessDisposeFileRequest(fileId);
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.DisposeFile)
.build();
}
else if (request.getRequestType().equals(RequestType.OutlineFile))
{
Integer fileId = request.getOutlineFileRequest().getFileIdentifier().getId();
System.out.println("Creating outline for id = " + fileId);
List<Outline> outline = Parser.ProcessOutlineRequest(fileId);
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.OutlineResults)
.setOutlineResultResponse(OutlineResultResponse.newBuilder()
.addAllOutline(outline)
.build())
.build();
}
else if (request.getRequestType().equals(RequestType.FileParseMessages))
{
Integer fileId = request.getFileParseMessagesRequest().getFileIdentifier().getId();
System.out.println("Sending squiggles for id = " + fileId);
List<Problem> problems = Parser.ProcessFileParseMessagesRequest(fileId);
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.FileParseMessages)
.setFileParseMessagesResponse(FileParseMessagesResponse.newBuilder()
.addAllProblems(problems)
.build())
.build();
}
else if (request.getRequestType().equals(RequestType.Autocomplete))
{
try
{
System.out.println("Autocomplete request for " + request.getAutocompleteRequest().getTypeRootIdentifier().getHandle());
List<Completion> proposals = Parser.ProcessAutocompleteRequest(
request.getAutocompleteRequest().getFileParseContents(),
request.getAutocompleteRequest().getTypeRootIdentifier().getHandle(),
request.getAutocompleteRequest().getCursorPosition());
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.Autocomplete)
.setAutocompleteResponse(AutocompleteResponse.newBuilder()
.setStatus(true)
.addAllProposals(proposals)
.build())
.build();
}
catch(Exception e)
{
e.printStackTrace();
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.Autocomplete)
.setAutocompleteResponse(AutocompleteResponse.newBuilder()
.setStatus(false)
.setErrorMessage(e.getMessage() != null ? e.getMessage() : e.toString())
.build())
.build();
}
}
else if (request.getRequestType().equals(RequestType.ParamHelp))
{
try
{
System.out.println("ParamHelp request for " + request.getParamHelpRequest().getTypeRootIdentifier().getHandle());
JavaParamHelpMatcher.ParamRegion region = Parser.getScope(
request.getParamHelpRequest().getFileParseContents(),
request.getParamHelpRequest().getCursorPosition());
List<Signature> signatures = Parser.ProcessParamHelpRequest(
request.getParamHelpRequest().getFileParseContents(),
request.getParamHelpRequest().getTypeRootIdentifier().getHandle(),
region.region.getOffset() + 1); // Request Autocomplete right after the open brace
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.ParamHelp)
.setParamHelpResponse(ParamHelpResponse.newBuilder()
.setStatus(true)
.addAllSignatures(signatures)
.setScopeStart(region.region.getOffset() + 1) // exclusive
.setScopeLength(region.region.getLength() - 2) // exclusive
.setParamCount(region.paramSeparatorCount)
.build())
.build();
}
catch(Exception e)
{
e.printStackTrace();
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.ParamHelp)
.setParamHelpResponse(ParamHelpResponse.newBuilder()
.setStatus(false)
.setErrorMessage(e.getMessage() != null ? e.getMessage() : e.toString())
.build())
.build();
}
}
else if (request.getRequestType().equals(RequestType.ParamHelpPositionUpdate))
{
try
{
System.out.println("ParamHelp PositionUpdate request for " + request.getParamHelpPositionUpdateRequest().getFileParseContents());
JavaParamHelpMatcher.ParamRegion region = Parser.updateScope(
request.getParamHelpPositionUpdateRequest().getFileParseContents(),
request.getParamHelpPositionUpdateRequest().getCursorPosition());
if (region == null)
throw new Exception("Outside of range");
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.ParamHelpPositionUpdate)
.setParamHelpPositionUpdateResponse(ParamHelpPositionUpdateResponse.newBuilder()
.setStatus(true)
.setParamCount(region.paramSeparatorCount)
.build())
.build();
}
catch(Exception e)
{
e.printStackTrace();
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.ParamHelpPositionUpdate)
.setParamHelpPositionUpdateResponse(ParamHelpPositionUpdateResponse.newBuilder()
.setStatus(false)
.setErrorMessage(e.getMessage() != null ? e.getMessage() : e.toString())
.build())
.build();
}
}
else if (request.getRequestType().equals(RequestType.QuickInfo))
{
try
{
System.out.println("QuickInfo request for " + request.getQuickInfoRequest().getTypeRootIdentifier().getHandle());
List<JavaElement> elements = Parser.ProcessQuickInfoRequest(
request.getQuickInfoRequest().getFileParseContents(),
request.getQuickInfoRequest().getTypeRootIdentifier().getHandle(),
request.getQuickInfoRequest().getCursorPosition());
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.QuickInfo)
.setQuickInfoResponse(QuickInfoResponse.newBuilder()
.addAllElements(elements)
.build())
.build();
}
catch(Exception e)
{
e.printStackTrace();
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.QuickInfo)
.setQuickInfoResponse(QuickInfoResponse.newBuilder()
.build())
.build();
}
}
else if (request.getRequestType().equals(RequestType.FindDefinition))
{
try
{
System.out.println("FindDefinition request for " + request.getFindDefinitionRequest().getTypeRootIdentifier().getHandle());
List<FindDefinitionResponse.JavaElement> elements = Parser.ProcessFindDefinintionRequest(
request.getFindDefinitionRequest().getFileParseContents(),
request.getFindDefinitionRequest().getTypeRootIdentifier().getHandle(),
request.getFindDefinitionRequest().getCursorPosition());
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.FindDefinition)
.setFindDefinitionResponse(FindDefinitionResponse.newBuilder()
.setStatus(true)
.setWorkspaceRootPath(Parser.WorkspaceRoot.getLocation().toString())
.addAllElements(elements)
.build())
.build();
}
catch(Exception e)
{
e.printStackTrace();
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.FindDefinition)
.setFindDefinitionResponse(FindDefinitionResponse.newBuilder()
.setStatus(false)
.setWorkspaceRootPath(Parser.WorkspaceRoot.getLocation().toString())
.setErrorMessage(e.getMessage() != null ? e.getMessage() : e.toString())
.build())
.build();
}
}
else if (request.getRequestType().equals(RequestType.OpenTypeRoot))
{
try
{
System.out.println("OpenTypeRoot request for " + request.getOpenTypeRootRequest().getFileName());
String typeRootHandle = Parser.ProcessOpenTypeRequest(request.getOpenTypeRootRequest().getFileName());
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.OpenTypeRoot)
.setOpenTypeRootResponse(OpenTypeRootResponse.newBuilder()
.setStatus(true)
.setTypeRootIdentifier(TypeRootIdentifier.newBuilder()
.setHandle(typeRootHandle)
.build())
.build())
.build();
}
catch(Exception e)
{
e.printStackTrace();
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.OpenTypeRoot)
.setOpenTypeRootResponse(OpenTypeRootResponse.newBuilder()
.setStatus(false)
.setErrorMessage(e.getMessage() != null ? e.getMessage() : e.toString())
.build())
.build();
}
}
else if (request.getRequestType().equals(RequestType.DisposeTypeRoot))
{
String handle = request.getDisposeTypeRootRequest().getTypeRootIdentifier().getHandle();
System.out.println("Remove typeroot for handle = " + handle);
Parser.ProcessDisposeTypeRoot(handle);
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.DisposeTypeRoot)
.build();
}
else if (request.getRequestType().equals(RequestType.AddTypeRoot))
{
try
{
System.out.println("AddTypeRoot request for " + request.getAddTypeRootRequest().getTypeRootIdentifier().getHandle());
String typeRootHandle = Parser.ProcessAddTypeRequest(request.getAddTypeRootRequest().getTypeRootIdentifier().getHandle());
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.AddTypeRoot)
.setAddTypeRootResponse(AddTypeRootResponse.newBuilder()
.setStatus(true)
.setTypeRootIdentifier(TypeRootIdentifier.newBuilder()
.setHandle(typeRootHandle)
.build())
.build())
.build();
}
catch(Exception e)
{
e.printStackTrace();
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.AddTypeRoot)
.setAddTypeRootResponse(AddTypeRootResponse.newBuilder()
.setStatus(false)
.setErrorMessage(e.getMessage() != null ? e.getMessage() : e.toString())
.build())
.build();
}
}
else // Bye message
{
return Protocol.Response.newBuilder()
.setResponseType(ResponseType.Bye)
.build();
}
}
}