/*
* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.errorprone.bugpatterns.testdata;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.errorprone.annotations.Immutable;
import java.util.Objects;
/** Negative test cases for the ConstructorLeaksThis checker. */
@Immutable
public class ConstructorLeaksThisNegativeCases {
// Named for com.google.testing.junit.junit4.rules.FixtureController,
// which is generally initialized with a leaked 'this'.
private static class FixtureController {
FixtureController(@SuppressWarnings("unused") Object testObject) {}
}
// Instance initializer containing some negative cases
{
// 'this' names the Runnable
MoreExecutors.directExecutor()
.execute(
new Runnable() {
@Override
public void run() {
new FixtureController(this);
}
});
}
public static class SafeReferences {
static final FixtureController that = new FixtureController(FixtureController.class);
final FixtureController controller = new FixtureController(that);
final int hash = Objects.hash(that);
final String str;
// Passing out references other than 'this' from a constructor is safe
public SafeReferences(String str) {
new FixtureController(str);
System.out.println(str);
// 'this' on the LHS is not a leak
this.str = "Hi";
// Extracting a field from this, assuming it's initialized,
// does not constitute a leak
System.out.println(this.str);
// This is silly but not unsafe
System.out.println(SafeReferences.this.str);
}
// Exporting 'this' from a regular method is safe
public void run() {
new FixtureController(this);
System.out.println(this);
}
}
// Safe because local variable is not a field
private void localVariable() {
int i = java.util.Objects.hashCode(this);
}
public static class ThisIsAnonymous {
ThisIsAnonymous() {
// 'this' names not the object under construction, but the Thread
new Thread() {
@Override
public void run() {
System.out.println(this);
}
}.start();
}
}
}