use network callback to update DNS config when network changes (#147)

* use network callback to update DNS config when network changes

-Use requestNetwork, which gets the best network matching the passed in network request, to listen for changes to network and cache DNS config
-Call netmon.InjectEvent on network change to indicate a change
Follow-up will fix issue in netmon where IsMajorChangeFrom doesn't identify major changes when a network is added

Fixes #10107

* use network callback to update DNS config when network changes

-Use requestNetwork, which gets the best network matching the passed in network request, to listen for changes to network and cache DNS config
-Call netmon.InjectEvent on network change to indicate a change
Follow-up will fix issue in netmon where IsMajorChangeFrom doesn't identify major changes when a network is added

Updates tailscale/tailscale/#10107

hi

* hi

* .

* use network callback to update DNS config when network changes

-Use requestNetwork, which gets the best network matching the passed in network request, to listen for changes to network and cache DNS config
-Call netmon.InjectEvent on network change to indicate a change
Follow-up will fix issue in netmon where IsMajorChangeFrom doesn't identify major changes when a network is added

Updates tailscale/tailscale/#10107

* fixed missing connectivity manager
pull/150/head
kari-ts 11 months ago committed by GitHub
parent 99c54591e6
commit 1b42117791
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- Disable input emulation on ChromeOS -->
<uses-feature android:name="android.hardware.type.pc" android:required="false"/>

@ -71,7 +71,7 @@ import androidx.browser.customtabs.CustomTabsIntent;
import org.gioui.Gio;
public class App extends Application {
private final static String PEER_TAG = "peer";
private static final String PEER_TAG = "peer";
static final String STATUS_CHANNEL_ID = "tailscale-status";
static final int STATUS_NOTIFICATION_ID = 1;
@ -82,16 +82,19 @@ public class App extends Application {
private static final String FILE_CHANNEL_ID = "tailscale-files";
private static final int FILE_NOTIFICATION_ID = 3;
private final static Handler mainHandler = new Handler(Looper.getMainLooper());
private static final Handler mainHandler = new Handler(Looper.getMainLooper());
public DnsConfig dns = new DnsConfig(this);
private ConnectivityManager connectivityManager;
public DnsConfig dns = new DnsConfig();
public DnsConfig getDnsConfigObj() { return this.dns; }
@Override public void onCreate() {
super.onCreate();
// Load and initialize the Go library.
Gio.init(this);
registerNetworkCallback();
this.connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
setAndRegisterNetworkCallbacks();
createNotificationChannel(NOTIFY_CHANNEL_ID, "Notifications", NotificationManagerCompat.IMPORTANCE_DEFAULT);
createNotificationChannel(STATUS_CHANNEL_ID, "VPN Status", NotificationManagerCompat.IMPORTANCE_LOW);
@ -99,26 +102,27 @@ public class App extends Application {
}
private void registerNetworkCallback() {
ConnectivityManager cMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
cMgr.registerNetworkCallback(new NetworkRequest.Builder().build(), new ConnectivityManager.NetworkCallback() {
private void reportConnectivityChange() {
NetworkInfo active = cMgr.getActiveNetworkInfo();
// https://developer.android.com/training/monitoring-device-state/connectivity-status-type
boolean isConnected = active != null && active.isConnectedOrConnecting();
onConnectivityChanged(isConnected);
// requestNetwork attempts to find the best network that matches the passed NetworkRequest. It is possible that
// this might return an unusuable network, eg a captive portal.
private void setAndRegisterNetworkCallbacks() {
connectivityManager.requestNetwork(dns.getDNSConfigNetworkRequest(), new ConnectivityManager.NetworkCallback(){
@Override
public void onAvailable(Network network){
super.onAvailable(network);
StringBuilder sb = new StringBuilder("");
LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
List<InetAddress> dnsList = linkProperties.getDnsServers();
for (InetAddress ip : dnsList) {
sb.append(ip.getHostAddress()).append(" ");
}
dns.updateDNSFromNetwork(sb.toString());
onDnsConfigChanged();
}
@Override
public void onLost(Network network) {
super.onLost(network);
this.reportConnectivityChange();
}
@Override
public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
super.onLinkPropertiesChanged(network, linkProperties);
this.reportConnectivityChange();
onDnsConfigChanged();
}
});
}
@ -347,7 +351,7 @@ public class App extends Application {
}
static native void onVPNPrepared();
private static native void onConnectivityChanged(boolean connected);
private static native void onDnsConfigChanged();
static native void onShareIntent(int nfiles, int[] types, String[] mimes, String[] items, String[] names, long[] sizes);
static native void onWriteStorageGranted();

@ -4,14 +4,8 @@
package com.tailscale.ipn;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.net.NetworkRequest;
import java.lang.reflect.Method;
@ -20,6 +14,8 @@ import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
// Tailscale DNS Config retrieval
//
@ -32,65 +28,9 @@ import java.util.Locale;
// Importantly, after the Tailscale VPN comes up it will set a DNS server of 100.100.100.100
// but we still want to retrieve the underlying DNS servers received from DHCP. If we roam
// from Wi-Fi to LTE, we want the DNS servers received from LTE.
//
// --------------------- Android 7 and later -----------------------------------------
//
// ## getDnsConfigFromLinkProperties
// Android provides a getAllNetworks interface in the ConnectivityManager. We walk through
// each interface to pick the most appropriate one.
// - If there is an Ethernet interface active we use that.
// - If Wi-Fi is active we use that.
// - If LTE is active we use that.
// - We never use a VPN's DNS servers. That VPN is likely us. Even if not us, Android
// only allows one VPN at a time so a different VPN's DNS servers won't be available
// once Tailscale comes up.
//
// getAllNetworks() is used as the sole mechanism for retrieving the DNS config with
// Android 7 and later.
//
// --------------------- Releases older than Android 7 -------------------------------
//
// We support Tailscale back to Android 5. Android versions 5 and 6 supply a getAllNetworks()
// implementation but it always returns an empty list.
//
// ## getDnsConfigFromLinkProperties with getActiveNetwork
// ConnectivityManager also supports a getActiveNetwork() routine, which Android 5 and 6 do
// return a value for. If Tailscale isn't up yet and we can get the Wi-Fi/LTE/etc DNS
// config using getActiveNetwork(), we use that.
//
// Once Tailscale is up, getActiveNetwork() returns tailscale0 with DNS server 100.100.100.100
// and that isn't useful. So we try two other mechanisms:
//
// ## getDnsServersFromSystemProperties
// Android versions prior to 8 let us retrieve the actual system DNS servers from properties.
// Later Android versions removed the properties and only return an empty string.
//
// We check the net.dns1 - net.dns4 DNS servers. If Tailscale is up the DNS server will be
// 100.100.100.100, which isn't useful, but if we get something different we'll use that.
//
// getDnsServersFromSystemProperties can only retrieve the IPv4 or IPv6 addresses of the
// configured DNS servers. We also want to know the DNS Search Domains configured, but
// we have no way to retrieve this using these interfaces. We return an empty list of
// search domains. Sorry.
//
// ## getDnsServersFromNetworkInfo
// ConnectivityManager supports an older API called getActiveNetworkInfo to return the
// active network interface. It doesn't handle VPNs, so the interface will always be Wi-Fi
// or Cellular even if Tailscale is up.
//
// For Wi-Fi interfaces we retrieve the DHCP response from the WifiManager. For Cellular
// interfaces we check for properties populated by most of the radio drivers.
//
// getDnsServersFromNetworkInfo does not have a way to retrieve the DNS Search Domains,
// so we return an empty list. Additionally, these interfaces are so old that they only
// support IPv4. We can't retrieve IPv6 DNS server addresses this way.
public class DnsConfig {
private Context ctx;
public DnsConfig(Context ctx) {
this.ctx = ctx;
}
private String dnsConfigs;
// getDnsConfigAsString returns the current DNS configuration as a multiline string:
// line[0] DNS server addresses separated by spaces
@ -102,260 +42,27 @@ public class DnsConfig {
//
// an empty string means the current DNS configuration could not be retrieved.
String getDnsConfigAsString() {
String s = getDnsConfigFromLinkProperties();
String s = getDnsConfigs();
if (!s.trim().isEmpty()) {
return s;
}
if (android.os.Build.VERSION.SDK_INT >= 23) {
// If ConnectivityManager.getAllNetworks() works, it is the
// authoritative mechanism and we rely on it. The other methods
// which follow involve more compromises.
return "";
}
s = getDnsServersFromSystemProperties();
if (!s.trim().isEmpty()) {
return s;
}
return getDnsServersFromNetworkInfo();
}
// getDnsConfigFromLinkProperties finds the DNS servers for each Network interface
// returned by ConnectivityManager getAllNetworks().LinkProperties, and return the
// one that (heuristically) would be the primary DNS servers.
//
// on a Nexus 4 with Android 5.1 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1
// on a Nexus 7 with Android 6.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1
// on a Pixel 3a with Android 12.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1\nlocaldomain
// on a Pixel 3a with Android 12.0 on LTE: fd00:976a::9 fd00:976a::10
//
// One odd behavior noted on Pixel3a with Android 12:
// With Wi-Fi already connected, starting Tailscale returned DNS servers 2602:248:7b4a:ff60::1 10.1.10.1
// Turning off Wi-Fi and connecting LTE returned DNS servers fd00:976a::9 fd00:976a::10.
// Turning Wi-Fi back on return DNS servers: 10.1.10.1. The IPv6 DNS server is gone.
// This appears to be the ConnectivityManager behavior, not something we are doing.
//
// This implementation can work through Android 12 (SDK 30). In SDK 31 the
// getAllNetworks() method is deprecated and we'll need to implement a
// android.net.ConnectivityManager.NetworkCallback instead to monitor
// link changes and track which DNS server to use.
String getDnsConfigFromLinkProperties() {
ConnectivityManager cMgr = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cMgr == null) {
return "";
}
Network[] networks = cMgr.getAllNetworks();
if (networks == null) {
// Android 6 and before often returns an empty list, but we
// can try again with just the active network.
//
// Once Tailscale is connected, the active network will be Tailscale
// which will have 100.100.100.100 for its DNS server. We reject
// TYPE_VPN in getPreferabilityForNetwork, so it won't be returned.
Network active = cMgr.getActiveNetwork();
if (active == null) {
return "";
}
networks = new Network[]{active};
}
// getPreferabilityForNetwork returns an index into dnsConfigs from 0-3.
String[] dnsConfigs = new String[]{"", "", "", ""};
for (Network network : networks) {
int idx = getPreferabilityForNetwork(cMgr, network);
if ((idx < 0) || (idx > 3)) {
continue;
}
LinkProperties linkProp = cMgr.getLinkProperties(network);
NetworkCapabilities nc = cMgr.getNetworkCapabilities(network);
List<InetAddress> dnsList = linkProp.getDnsServers();
StringBuilder sb = new StringBuilder("");
for (InetAddress ip : dnsList) {
sb.append(ip.getHostAddress() + " ");
}
String d = linkProp.getDomains();
if (d != null) {
sb.append("\n");
sb.append(d);
}
dnsConfigs[idx] = sb.toString();
}
// return the lowest index DNS config which exists. If an Ethernet config
// was found, return it. Otherwise if Wi-fi was found, return it. Etc.
for (String s : dnsConfigs) {
if (!s.trim().isEmpty()) {
return s;
}
}
return "";
}
// getDnsServersFromSystemProperties returns DNS servers found in system properties.
// On Android versions prior to Android 8, we can directly query the DNS
// servers the system is using. More recent Android releases return empty strings.
//
// Once Tailscale is connected these properties will return 100.100.100.100, which we
// suppress.
//
// on a Nexus 4 with Android 5.1 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1
// on a Nexus 7 with Android 6.0 on wifi: 2602:248:7b4a:ff60::1 10.1.10.1
// on a Pixel 3a with Android 12.0 on wifi:
// on a Pixel 3a with Android 12.0 on LTE:
//
// The list of DNS search domains does not appear to be available in system properties.
String getDnsServersFromSystemProperties() {
try {
Class SystemProperties = Class.forName("android.os.SystemProperties");
Method method = SystemProperties.getMethod("get", String.class);
List<String> servers = new ArrayList<String>();
for (String name : new String[]{"net.dns1", "net.dns2", "net.dns3", "net.dns4"}) {
String value = (String) method.invoke(null, name);
if (value != null && !value.isEmpty() &&
!value.equals("100.100.100.100") &&
!servers.contains(value)) {
servers.add(value);
}
}
return String.join(" ", servers);
} catch (Exception e) {
return "";
private String getDnsConfigs(){
synchronized(this) {
return this.dnsConfigs;
}
}
public String intToInetString(int hostAddress) {
return String.format(java.util.Locale.ROOT, "%d.%d.%d.%d",
(0xff & hostAddress),
(0xff & (hostAddress >> 8)),
(0xff & (hostAddress >> 16)),
(0xff & (hostAddress >> 24)));
}
// getDnsServersFromNetworkInfo retrieves DNS servers using ConnectivityManager
// getActiveNetworkInfo() plus interface-specific mechanisms to retrieve the DNS servers.
// Only IPv4 DNS servers are supported by this mechanism, neither the WifiManager nor the
// interface-specific dns properties appear to populate IPv6 DNS server addresses.
//
// on a Nexus 4 with Android 5.1 on wifi: 10.1.10.1
// on a Nexus 7 with Android 6.0 on wifi: 10.1.10.1
// on a Pixel-3a with Android 12.0 on wifi: 10.1.10.1
// on a Pixel-3a with Android 12.0 on LTE:
//
// The list of DNS search domains is not available in this way.
String getDnsServersFromNetworkInfo() {
ConnectivityManager cMgr = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cMgr == null) {
return "";
}
NetworkInfo info = cMgr.getActiveNetworkInfo();
if (info == null) {
return "";
void updateDNSFromNetwork(String dnsConfigs){
synchronized(this) {
this.dnsConfigs = dnsConfigs;
}
Class SystemProperties;
Method method;
try {
SystemProperties = Class.forName("android.os.SystemProperties");
method = SystemProperties.getMethod("get", String.class);
} catch (Exception e) {
return "";
}
List<String> servers = new ArrayList<String>();
switch(info.getType()) {
case ConnectivityManager.TYPE_WIFI:
case ConnectivityManager.TYPE_WIMAX:
for (String name : new String[]{
"net.wifi0.dns1", "net.wifi0.dns2", "net.wifi0.dns3", "net.wifi0.dns4",
"net.wlan0.dns1", "net.wlan0.dns2", "net.wlan0.dns3", "net.wlan0.dns4",
"net.eth0.dns1", "net.eth0.dns2", "net.eth0.dns3", "net.eth0.dns4",
"dhcp.wlan0.dns1", "dhcp.wlan0.dns2", "dhcp.wlan0.dns3", "dhcp.wlan0.dns4",
"dhcp.tiwlan0.dns1", "dhcp.tiwlan0.dns2", "dhcp.tiwlan0.dns3", "dhcp.tiwlan0.dns4"}) {
try {
String value = (String) method.invoke(null, name);
if (value != null && !value.isEmpty() && !servers.contains(value)) {
servers.add(value);
}
} catch (Exception e) {
continue;
}
}
WifiManager wMgr = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE);
if (wMgr != null) {
DhcpInfo dhcp = wMgr.getDhcpInfo();
if (dhcp.dns1 != 0) {
String value = intToInetString(dhcp.dns1);
if (value != null && !value.isEmpty() && !servers.contains(value)) {
servers.add(value);
}
}
if (dhcp.dns2 != 0) {
String value = intToInetString(dhcp.dns2);
if (value != null && !value.isEmpty() && !servers.contains(value)) {
servers.add(value);
}
}
}
return String.join(" ", servers);
case ConnectivityManager.TYPE_MOBILE:
case ConnectivityManager.TYPE_MOBILE_HIPRI:
for (String name : new String[]{
"net.rmnet0.dns1", "net.rmnet0.dns2", "net.rmnet0.dns3", "net.rmnet0.dns4",
"net.rmnet1.dns1", "net.rmnet1.dns2", "net.rmnet1.dns3", "net.rmnet1.dns4",
"net.rmnet2.dns1", "net.rmnet2.dns2", "net.rmnet2.dns3", "net.rmnet2.dns4",
"net.rmnet3.dns1", "net.rmnet3.dns2", "net.rmnet3.dns3", "net.rmnet3.dns4",
"net.rmnet4.dns1", "net.rmnet4.dns2", "net.rmnet4.dns3", "net.rmnet4.dns4",
"net.rmnet5.dns1", "net.rmnet5.dns2", "net.rmnet5.dns3", "net.rmnet5.dns4",
"net.rmnet6.dns1", "net.rmnet6.dns2", "net.rmnet6.dns3", "net.rmnet6.dns4",
"net.rmnet7.dns1", "net.rmnet7.dns2", "net.rmnet7.dns3", "net.rmnet7.dns4",
"net.pdp0.dns1", "net.pdp0.dns2", "net.pdp0.dns3", "net.pdp0.dns4",
"net.pdpbr0.dns1", "net.pdpbr0.dns2", "net.pdpbr0.dns3", "net.pdpbr0.dns4"}) {
try {
String value = (String) method.invoke(null, name);
if (value != null && !value.isEmpty() && !servers.contains(value)) {
servers.add(value);
}
} catch (Exception e) {
continue;
}
}
}
return "";
}
// getPreferabilityForNetwork is a utility routine which implements a priority for
// different types of network transport, used in a heuristic to pick DNS servers to use.
int getPreferabilityForNetwork(ConnectivityManager cMgr, Network network) {
NetworkCapabilities nc = cMgr.getNetworkCapabilities(network);
if (nc == null) {
return -1;
}
if (nc.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
// tun0 has both VPN and WIFI set, have to check VPN first and return.
return -1;
}
if (nc.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
return 0;
} else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return 1;
} else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return 2;
} else {
return 3;
}
NetworkRequest getDNSConfigNetworkRequest(){
// Request networks that are able to reach the Internet.
return new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
}
}

@ -1,21 +0,0 @@
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import com.tailscale.ipn.DnsConfig;
public class DnsConfigTest {
DnsConfig dns;
@Before
public void setup() {
dns = new DnsConfig(null);
}
@Test
public void dnsConfig_intToInetStringTest() {
assertEquals(dns.intToInetString(0x0101a8c0), "192.168.1.1");
assertEquals(dns.intToInetString(0x04030201), "1.2.3.4");
assertEquals(dns.intToInetString(0), "0.0.0.0");
}
}

@ -184,7 +184,7 @@ func (b *backend) Start(notify func(n ipn.Notify)) error {
return b.backend.Start(ipn.Options{})
}
func (b *backend) LinkChange() {
func (b *backend) NetworkChanged() {
if b.sys != nil {
if nm, ok := b.sys.NetMon.GetOK(); ok {
nm.InjectEvent()

@ -30,9 +30,6 @@ var (
// onDisconnect receives global IPNService references when
// disconnecting.
onDisconnect = make(chan jni.Object)
// onConnectivityChange is notified every time the network
// conditions change.
onConnectivityChange = make(chan bool, 1)
// onGoogleToken receives google ID tokens.
onGoogleToken = make(chan string)
@ -42,6 +39,9 @@ var (
// onWriteStorageGranted is notified when we are granted WRITE_STORAGE_PERMISSION.
onWriteStorageGranted = make(chan struct{}, 1)
// onDNSConfigChanged is notified when the network changes and the DNS config needs to be updated.
onDNSConfigChanged = make(chan struct{}, 1)
)
const (
@ -109,21 +109,12 @@ func Java_com_tailscale_ipn_IPNService_disconnect(env *C.JNIEnv, this C.jobject)
//export Java_com_tailscale_ipn_StartVPNWorker_connect
func Java_com_tailscale_ipn_StartVPNWorker_connect(env *C.JNIEnv, this C.jobject) {
requestBackend(ConnectEvent{Enable: true})
requestBackend(ConnectEvent{Enable: true})
}
//export Java_com_tailscale_ipn_StopVPNWorker_disconnect
func Java_com_tailscale_ipn_StopVPNWorker_disconnect(env *C.JNIEnv, this C.jobject) {
requestBackend(ConnectEvent{Enable: false})
}
//export Java_com_tailscale_ipn_App_onConnectivityChanged
func Java_com_tailscale_ipn_App_onConnectivityChanged(env *C.JNIEnv, cls C.jclass, connected C.jboolean) {
select {
case <-onConnectivityChange:
default:
}
onConnectivityChange <- connected == C.JNI_TRUE
requestBackend(ConnectEvent{Enable: false})
}
//export Java_com_tailscale_ipn_QuickToggleService_onTileClick
@ -200,3 +191,11 @@ func Java_com_tailscale_ipn_App_onShareIntent(env *C.JNIEnv, cls C.jclass, nfile
}
onFileShare <- files
}
//export Java_com_tailscale_ipn_App_onDnsConfigChanged
func Java_com_tailscale_ipn_App_onDnsConfigChanged(env *C.JNIEnv, cls C.jclass) {
select {
case onDNSConfigChanged <- struct{}{}:
default:
}
}

@ -526,11 +526,6 @@ func (a *App) runBackend() error {
notifyVPNClosed()
}
}
case <-onConnectivityChange:
if b != nil {
go b.LinkChange()
}
a.notify(state)
case s := <-onDisconnect:
b.CloseTUNs()
jni.Do(a.jvm, func(env *jni.Env) error {
@ -545,6 +540,11 @@ func (a *App) runBackend() error {
if state.State >= ipn.Starting {
notifyVPNClosed()
}
case <-onDNSConfigChanged:
if b != nil {
go b.NetworkChanged()
}
a.notify(state)
}
}
}

@ -0,0 +1,315 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="13">
<profile kind="CodeFormatterProfile" name="Eclipse" version="13">
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="10"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="10"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.compiler.source" value="10"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
</profile>
</profiles>
Loading…
Cancel
Save