package org.erlide.engine.internal.services.parsing; import java.util.ArrayList; import java.util.List; import org.erlide.engine.ErlangEngine; import org.erlide.engine.services.parsing.ErlToken; import org.erlide.engine.services.parsing.InternalScanner; import org.erlide.engine.services.parsing.ScannerException; import org.erlide.engine.services.parsing.SimpleScannerService; import org.erlide.runtime.rpc.IOtpRpc; import org.erlide.runtime.rpc.RpcException; import org.erlide.runtime.rpc.RpcTimeoutException; import org.erlide.util.ErlLogger; import org.erlide.util.Util; import com.ericsson.otp.erlang.OtpErlangBinary; import com.ericsson.otp.erlang.OtpErlangObject; import com.ericsson.otp.erlang.OtpErlangTuple; public class ErlideScanner implements SimpleScannerService, InternalScanner { private static final String ERLIDE_SCANNER = "erlide_scanner"; private static final Object ENCODING = System.getProperty("erlide.encoding.__test__", "latin1"); private static final boolean USE_CACHE = true; private final IOtpRpc backend; public ErlideScanner(final IOtpRpc backend) { this.backend = backend; } public void initialScan(final String module, final String path, final String initialText) { final String stateDir = ErlangEngine.getInstance().getStateDir(); try { backend.call(ERLIDE_SCANNER, "initial_scan", "assso", module, path, initialText == null ? "" : initialText, stateDir, USE_CACHE); } catch (final RpcTimeoutException e) { ErlLogger.debug(e); } catch (final Exception e) { ErlLogger.debug(e); } } @Override public void create(final String module) { try { backend.call(ERLIDE_SCANNER, "create", "a", module); } catch (final RpcTimeoutException e) { ErlLogger.debug(e); } catch (final Exception e) { ErlLogger.debug(e); } } public void addref(final String module) { try { backend.call(ERLIDE_SCANNER, "addref", "a", module); } catch (final RpcTimeoutException e) { ErlLogger.debug(e); } catch (final Exception e) { ErlLogger.debug(e); } } public void dispose(final String module) { try { backend.call(ERLIDE_SCANNER, "dispose", "a", module); } catch (final RpcTimeoutException e) { ErlLogger.debug(e); } catch (final Exception e) { ErlLogger.debug(e); } } @SuppressWarnings("boxing") public ErlToken getTokenAt(final String module, final int offset) { OtpErlangObject r1 = null; try { r1 = backend.call(ERLIDE_SCANNER, "get_token_at", "ai", module, offset); } catch (final Exception e) { return null; } if (!(r1 instanceof OtpErlangTuple)) { return null; } final OtpErlangTuple t1 = (OtpErlangTuple) r1; if (Util.isOk(t1)) { final OtpErlangObject ot = t1.elementAt(1); if (ot instanceof OtpErlangTuple) { final OtpErlangTuple tt = (OtpErlangTuple) ot; return new ErlToken(tt); } } return null; } @SuppressWarnings("boxing") public void replaceText(final String module, final int offset, final int removeLength, final String newText) { try { final OtpErlangObject r = backend.call(ERLIDE_SCANNER, "replace_text", "aiis", module, offset, removeLength, newText); if (r instanceof OtpErlangTuple) { ErlLogger.error("replace_text %s @ %d GOT:: %s", module, offset, r.toString()); } } catch (final RpcTimeoutException e) { ErlLogger.debug(e); } catch (final RpcException e) { ErlLogger.debug(e); } } @Override public List<ErlToken> lightScanString(final String string, final int offset) throws ScannerException { OtpErlangObject r1 = null; try { r1 = backend.call("erlide_scanner", "light_scan_string", "ba", string, ENCODING); } catch (final Exception e) { throw new ScannerException( "Could not parse string \"" + string + "\": " + e.getMessage()); } if (r1 == null) { return null; } if (!(r1 instanceof OtpErlangTuple)) { throw new ScannerException("Could not parse string \"" + string + "\": weird return value " + r1); } final OtpErlangTuple t1 = (OtpErlangTuple) r1; List<ErlToken> toks = null; if (Util.isOk(t1)) { if (t1.elementAt(1) instanceof OtpErlangBinary) { final OtpErlangBinary b = (OtpErlangBinary) t1.elementAt(1); final byte[] bytes = b.binaryValue(); toks = new ArrayList<>(bytes.length / 10); for (int i = 0; i < bytes.length; i += 10) { final ErlToken tk = new ErlToken(bytes, i, offset); toks.add(tk); } return toks; } throw new ScannerException("unexpected token format"); } throw new ScannerException( "Could not parse string \"" + string + "\": " + t1.toString()); } @Override public OtpErlangObject checkAll(final String module, final String text, final boolean getTokens) { if (module == null) { return null; } try { final OtpErlangObject o = backend.call(ERLIDE_SCANNER, "check_all", "aso", module, text, getTokens); return o; } catch (final RpcException e) { ErlLogger.warn(e); } return null; } }