Initial commit 🎉
fbshipit-source-id: b6fc29740c6875d2e78953b8a7123890a67930f2 Co-authored-by: Sebastian McKenzie <sebmck@fb.com> Co-authored-by: John Knox <jknox@fb.com> Co-authored-by: Emil Sjölander <emilsj@fb.com> Co-authored-by: Pritesh Nandgaonkar <prit91@fb.com>
This commit is contained in:
34
android/core/ErrorReportingRunnable.java
Normal file
34
android/core/ErrorReportingRunnable.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
public abstract class ErrorReportingRunnable implements Runnable {
|
||||
|
||||
private final SonarConnection mConnection;
|
||||
|
||||
public ErrorReportingRunnable(SonarConnection connection) {
|
||||
mConnection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
try {
|
||||
runOrThrow();
|
||||
} catch (Exception e) {
|
||||
if (mConnection != null) {
|
||||
mConnection.reportError(e);
|
||||
}
|
||||
} finally {
|
||||
doFinally();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doFinally() {}
|
||||
|
||||
protected abstract void runOrThrow() throws Exception;
|
||||
}
|
||||
164
android/core/SonarArray.java
Normal file
164
android/core/SonarArray.java
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class SonarArray {
|
||||
final JSONArray mJson;
|
||||
|
||||
SonarArray(JSONArray json) {
|
||||
mJson = (json != null ? json : new JSONArray());
|
||||
}
|
||||
|
||||
SonarArray(String json) {
|
||||
try {
|
||||
mJson = new JSONArray(json);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SonarDynamic getDynamic(int index) {
|
||||
return new SonarDynamic(mJson.opt(index));
|
||||
}
|
||||
|
||||
public String getString(int index) {
|
||||
return mJson.optString(index);
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return mJson.optInt(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return mJson.optLong(index);
|
||||
}
|
||||
|
||||
public float getFloat(int index) {
|
||||
return (float) mJson.optDouble(index);
|
||||
}
|
||||
|
||||
public double getDouble(int index) {
|
||||
return mJson.optDouble(index);
|
||||
}
|
||||
|
||||
public boolean getBoolean(int index) {
|
||||
return mJson.optBoolean(index);
|
||||
}
|
||||
|
||||
public SonarObject getObject(int index) {
|
||||
final Object o = mJson.opt(index);
|
||||
return new SonarObject((JSONObject) o);
|
||||
}
|
||||
|
||||
public SonarArray getArray(int index) {
|
||||
final Object o = mJson.opt(index);
|
||||
return new SonarArray((JSONArray) o);
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return mJson.length();
|
||||
}
|
||||
|
||||
public List<String> toStringList() {
|
||||
final int length = length();
|
||||
final List<String> list = new ArrayList<>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
list.add(getString(i));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public String toJsonString() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mJson.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return mJson.toString().equals(o.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mJson.hashCode();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final JSONArray mJson;
|
||||
|
||||
public Builder() {
|
||||
mJson = new JSONArray();
|
||||
}
|
||||
|
||||
public Builder put(String s) {
|
||||
mJson.put(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(Integer i) {
|
||||
mJson.put(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(Long l) {
|
||||
mJson.put(l);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(Float f) {
|
||||
mJson.put(Float.isNaN(f) ? null : f);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(Double d) {
|
||||
mJson.put(Double.isNaN(d) ? null : d);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(Boolean b) {
|
||||
mJson.put(b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(SonarValue v) {
|
||||
return put(v.toSonarObject());
|
||||
}
|
||||
|
||||
public Builder put(SonarArray a) {
|
||||
mJson.put(a == null ? null : a.mJson);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(SonarArray.Builder b) {
|
||||
return put(b.build());
|
||||
}
|
||||
|
||||
public Builder put(SonarObject o) {
|
||||
mJson.put(o == null ? null : o.mJson);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(SonarObject.Builder b) {
|
||||
return put(b.build());
|
||||
}
|
||||
|
||||
public SonarArray build() {
|
||||
return new SonarArray(mJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
20
android/core/SonarClient.java
Normal file
20
android/core/SonarClient.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
public interface SonarClient {
|
||||
void addPlugin(SonarPlugin plugin);
|
||||
|
||||
<T extends SonarPlugin> T getPlugin(String id);
|
||||
|
||||
void removePlugin(SonarPlugin plugin);
|
||||
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
}
|
||||
37
android/core/SonarConnection.java
Normal file
37
android/core/SonarConnection.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
/**
|
||||
* A connection between a SonarPlugin and the desktop Sonar application. Register request handlers
|
||||
* to respond to calls made by the desktop application or directly send messages to the desktop
|
||||
* application.
|
||||
*/
|
||||
public interface SonarConnection {
|
||||
|
||||
/**
|
||||
* Call a remote method on the Sonar desktop application, passing an optional JSON object as a
|
||||
* parameter.
|
||||
*/
|
||||
void send(String method, SonarObject params);
|
||||
|
||||
/**
|
||||
* Call a remote method on the Sonar desktop application, passing an optional JSON array as a
|
||||
* parameter.
|
||||
*/
|
||||
void send(String method, SonarArray params);
|
||||
|
||||
/** Report client error */
|
||||
void reportError(Throwable throwable);
|
||||
|
||||
/**
|
||||
* Register a receiver for a remote method call issued by the Sonar desktop application. The
|
||||
* SonarReceiver is passed a responder to respond back to the desktop application.
|
||||
*/
|
||||
void receive(String method, SonarReceiver receiver);
|
||||
}
|
||||
124
android/core/SonarDynamic.java
Normal file
124
android/core/SonarDynamic.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class SonarDynamic {
|
||||
private final Object mObject;
|
||||
|
||||
public SonarDynamic(Object object) {
|
||||
mObject = object;
|
||||
}
|
||||
|
||||
public @Nullable String asString() {
|
||||
if (mObject == null) {
|
||||
return null;
|
||||
}
|
||||
return mObject.toString();
|
||||
}
|
||||
|
||||
public int asInt() {
|
||||
if (mObject == null) {
|
||||
return 0;
|
||||
}
|
||||
if (mObject instanceof Integer) {
|
||||
return (Integer) mObject;
|
||||
}
|
||||
if (mObject instanceof Long) {
|
||||
return ((Long) mObject).intValue();
|
||||
}
|
||||
if (mObject instanceof Float) {
|
||||
return ((Float) mObject).intValue();
|
||||
}
|
||||
if (mObject instanceof Double) {
|
||||
return ((Double) mObject).intValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long asLong() {
|
||||
if (mObject == null) {
|
||||
return 0;
|
||||
}
|
||||
if (mObject instanceof Integer) {
|
||||
return (Integer) mObject;
|
||||
}
|
||||
if (mObject instanceof Long) {
|
||||
return (Long) mObject;
|
||||
}
|
||||
if (mObject instanceof Float) {
|
||||
return ((Float) mObject).longValue();
|
||||
}
|
||||
if (mObject instanceof Double) {
|
||||
return ((Double) mObject).longValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public float asFloat() {
|
||||
if (mObject == null) {
|
||||
return 0;
|
||||
}
|
||||
if (mObject instanceof Integer) {
|
||||
return (Integer) mObject;
|
||||
}
|
||||
if (mObject instanceof Long) {
|
||||
return (Long) mObject;
|
||||
}
|
||||
if (mObject instanceof Float) {
|
||||
return (Float) mObject;
|
||||
}
|
||||
if (mObject instanceof Double) {
|
||||
return ((Double) mObject).floatValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double asDouble() {
|
||||
if (mObject == null) {
|
||||
return 0;
|
||||
}
|
||||
if (mObject instanceof Integer) {
|
||||
return (Integer) mObject;
|
||||
}
|
||||
if (mObject instanceof Long) {
|
||||
return (Long) mObject;
|
||||
}
|
||||
if (mObject instanceof Float) {
|
||||
return (Float) mObject;
|
||||
}
|
||||
if (mObject instanceof Double) {
|
||||
return (Double) mObject;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean asBoolean() {
|
||||
if (mObject == null) {
|
||||
return false;
|
||||
}
|
||||
return (Boolean) mObject;
|
||||
}
|
||||
|
||||
public SonarObject asObject() {
|
||||
if (mObject instanceof JSONObject) {
|
||||
return new SonarObject((JSONObject) mObject);
|
||||
}
|
||||
return (SonarObject) mObject;
|
||||
}
|
||||
|
||||
public SonarArray asArray() {
|
||||
if (mObject instanceof JSONArray) {
|
||||
return new SonarArray((JSONArray) mObject);
|
||||
}
|
||||
return (SonarArray) mObject;
|
||||
}
|
||||
}
|
||||
221
android/core/SonarObject.java
Normal file
221
android/core/SonarObject.java
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class SonarObject {
|
||||
final JSONObject mJson;
|
||||
|
||||
public SonarObject(JSONObject json) {
|
||||
mJson = (json != null ? json : new JSONObject());
|
||||
}
|
||||
|
||||
public SonarObject(String json) {
|
||||
try {
|
||||
mJson = new JSONObject(json);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SonarDynamic getDynamic(String name) {
|
||||
return new SonarDynamic(mJson.opt(name));
|
||||
}
|
||||
|
||||
public String getString(String name) {
|
||||
if (mJson.isNull(name)) {
|
||||
return null;
|
||||
}
|
||||
return mJson.optString(name);
|
||||
}
|
||||
|
||||
public int getInt(String name) {
|
||||
return mJson.optInt(name);
|
||||
}
|
||||
|
||||
public long getLong(String name) {
|
||||
return mJson.optLong(name);
|
||||
}
|
||||
|
||||
public float getFloat(String name) {
|
||||
return (float) mJson.optDouble(name);
|
||||
}
|
||||
|
||||
public double getDouble(String name) {
|
||||
return mJson.optDouble(name);
|
||||
}
|
||||
|
||||
public boolean getBoolean(String name) {
|
||||
return mJson.optBoolean(name);
|
||||
}
|
||||
|
||||
public SonarObject getObject(String name) {
|
||||
final Object o = mJson.opt(name);
|
||||
return new SonarObject((JSONObject) o);
|
||||
}
|
||||
|
||||
public SonarArray getArray(String name) {
|
||||
final Object o = mJson.opt(name);
|
||||
return new SonarArray((JSONArray) o);
|
||||
}
|
||||
|
||||
public boolean contains(String name) {
|
||||
return mJson.has(name);
|
||||
}
|
||||
|
||||
public String toJsonString() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mJson.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return mJson.toString().equals(o.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mJson.hashCode();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final JSONObject mJson;
|
||||
|
||||
public Builder() {
|
||||
mJson = new JSONObject();
|
||||
}
|
||||
|
||||
public Builder put(String name, Object obj) {
|
||||
if (obj == null) {
|
||||
return put(name, (String) null);
|
||||
} else if (obj instanceof Integer) {
|
||||
return put(name, (Integer) obj);
|
||||
} else if (obj instanceof Long) {
|
||||
return put(name, (Long) obj);
|
||||
} else if (obj instanceof Float) {
|
||||
return put(name, (Float) obj);
|
||||
} else if (obj instanceof Double) {
|
||||
return put(name, (Double) obj);
|
||||
} else if (obj instanceof String) {
|
||||
return put(name, (String) obj);
|
||||
} else if (obj instanceof Boolean) {
|
||||
return put(name, (Boolean) obj);
|
||||
} else if (obj instanceof Object[]) {
|
||||
return put(name, Arrays.deepToString((Object[]) obj));
|
||||
} else if (obj instanceof SonarObject) {
|
||||
return put(name, (SonarObject) obj);
|
||||
} else if (obj instanceof SonarObject.Builder) {
|
||||
return put(name, (SonarObject.Builder) obj);
|
||||
} else if (obj instanceof SonarArray) {
|
||||
return put(name, (SonarArray) obj);
|
||||
} else if (obj instanceof SonarArray.Builder) {
|
||||
return put(name, (SonarArray.Builder) obj);
|
||||
} else if (obj instanceof SonarValue) {
|
||||
return put(name, ((SonarValue) obj).toSonarObject());
|
||||
} else {
|
||||
return put(name, obj.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public Builder put(String name, String s) {
|
||||
try {
|
||||
mJson.put(name, s);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(String name, Integer i) {
|
||||
try {
|
||||
mJson.put(name, i);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(String name, Long l) {
|
||||
try {
|
||||
mJson.put(name, l);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(String name, Float f) {
|
||||
try {
|
||||
mJson.put(name, Float.isNaN(f) ? null : f);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(String name, Double d) {
|
||||
try {
|
||||
mJson.put(name, Double.isNaN(d) ? null : d);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(String name, Boolean b) {
|
||||
try {
|
||||
mJson.put(name, b);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(String name, SonarValue v) {
|
||||
return put(name, v.toSonarObject());
|
||||
}
|
||||
|
||||
public Builder put(String name, SonarArray a) {
|
||||
try {
|
||||
mJson.put(name, a == null ? null : a.mJson);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(String name, SonarArray.Builder b) {
|
||||
return put(name, b.build());
|
||||
}
|
||||
|
||||
public Builder put(String name, SonarObject o) {
|
||||
try {
|
||||
mJson.put(name, o == null ? null : o.mJson);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder put(String name, SonarObject.Builder b) {
|
||||
return put(name, b.build());
|
||||
}
|
||||
|
||||
public SonarObject build() {
|
||||
return new SonarObject(mJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
android/core/SonarPlugin.java
Normal file
37
android/core/SonarPlugin.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
/**
|
||||
* A SonarPlugin is an object which exposes an API to the Desktop Sonar application. When a
|
||||
* connection is established the plugin is given a SonarConnection on which it can register request
|
||||
* handlers and send messages. When the SonarConnection is invalid onDisconnect is called. onConnect
|
||||
* may be called again on the same plugin object if Sonar re-connects, this will provide a new
|
||||
* SonarConnection, do not attempt to re-use the previous connection.
|
||||
*/
|
||||
public interface SonarPlugin {
|
||||
|
||||
/**
|
||||
* @return The id of this plugin. This is the namespace which Sonar desktop plugins will call
|
||||
* methods on to route them to your plugin. This should match the id specified in your React
|
||||
* plugin.
|
||||
*/
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Called when a connection has been established. The connection passed to this method is valid
|
||||
* until {@link SonarPlugin#onDisconnect()} is called.
|
||||
*/
|
||||
void onConnect(SonarConnection connection) throws Exception;
|
||||
|
||||
/**
|
||||
* Called when the connection passed to {@link SonarPlugin#onConnect(SonarConnection)} is no
|
||||
* longer valid. Do not try to use the connection in or after this method has been called.
|
||||
*/
|
||||
void onDisconnect() throws Exception;
|
||||
}
|
||||
25
android/core/SonarReceiver.java
Normal file
25
android/core/SonarReceiver.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
/**
|
||||
* A receiver of a remote method call issued by the Sonar desktop application. If the given
|
||||
* responder is present it means the Sonar desktop application is expecting a response.
|
||||
*/
|
||||
public interface SonarReceiver {
|
||||
|
||||
/**
|
||||
* Reciver for a request sent from the Sonar desktop client.
|
||||
*
|
||||
* @param params Optional set of parameters sent with the request.
|
||||
* @param responder Optional responder for request. Some requests don't warrant a response
|
||||
* through. In this case the request should be made from the desktop using send() instead of
|
||||
* call().
|
||||
*/
|
||||
void onReceive(SonarObject params, SonarResponder responder) throws Exception;
|
||||
}
|
||||
28
android/core/SonarResponder.java
Normal file
28
android/core/SonarResponder.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
/**
|
||||
* SonarResponder is used to asyncronously response to a messaged recieved from the Sonar desktop
|
||||
* app. The Sonar Responder will automatically wrap the response in an approriate object depending
|
||||
* on if it is an error or not.
|
||||
*/
|
||||
public interface SonarResponder {
|
||||
|
||||
/** Deliver a successful response to the Sonar desktop app. */
|
||||
void success(SonarObject response);
|
||||
|
||||
/** Deliver a successful response to the Sonar desktop app. */
|
||||
void success(SonarArray response);
|
||||
|
||||
/** Deliver a successful response to the Sonar desktop app. */
|
||||
void success();
|
||||
|
||||
/** Inform the Sonar desktop app of an error in handling the request. */
|
||||
void error(SonarObject response);
|
||||
}
|
||||
12
android/core/SonarValue.java
Normal file
12
android/core/SonarValue.java
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
package com.facebook.sonar.core;
|
||||
|
||||
public interface SonarValue {
|
||||
SonarObject toSonarObject();
|
||||
}
|
||||
Reference in New Issue
Block a user