diff --git a/annotations/src/main/java/com/google/errorprone/annotations/concurrent/LockMethod.java b/annotations/src/main/java/com/google/errorprone/annotations/concurrent/LockMethod.java index a330a2e86c0..1abfdab2023 100644 --- a/annotations/src/main/java/com/google/errorprone/annotations/concurrent/LockMethod.java +++ b/annotations/src/main/java/com/google/errorprone/annotations/concurrent/LockMethod.java @@ -42,9 +42,12 @@ *
  • method-name(): The lock object is returned by calling the named nullary * method. * + * + * @deprecated the correctness of this annotation is not enforced; it will soon be removed. */ @Target(METHOD) @Retention(CLASS) +@Deprecated public @interface LockMethod { String[] value(); } diff --git a/annotations/src/main/java/com/google/errorprone/annotations/concurrent/UnlockMethod.java b/annotations/src/main/java/com/google/errorprone/annotations/concurrent/UnlockMethod.java index 05713d6a1f0..9437f66b9dd 100644 --- a/annotations/src/main/java/com/google/errorprone/annotations/concurrent/UnlockMethod.java +++ b/annotations/src/main/java/com/google/errorprone/annotations/concurrent/UnlockMethod.java @@ -42,9 +42,12 @@ *
  • method-name(): The lock object is returned by calling the named nullary * method. * + * + * @deprecated the correctness of this annotation is not enforced; it will soon be removed. */ @Target(METHOD) @Retention(CLASS) +@Deprecated public @interface UnlockMethod { String[] value(); } diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/AbstractLockMethodChecker.java b/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/AbstractLockMethodChecker.java deleted file mode 100644 index 649bf1d3766..00000000000 --- a/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/AbstractLockMethodChecker.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * 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.threadsafety; - -import com.google.common.base.Functions; -import com.google.common.base.Joiner; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import com.google.common.collect.Sets.SetView; -import com.google.errorprone.VisitorState; -import com.google.errorprone.bugpatterns.BugChecker; -import com.google.errorprone.matchers.Description; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.Tree; -import java.util.Comparator; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -/** - * Abstract implementation of checkers for {@code @LockMethod} and{@code @UnlockMethod}. - * - * @author cushon@google.com (Liam Miller-Cushon) - */ -public abstract class AbstractLockMethodChecker extends BugChecker - implements BugChecker.MethodTreeMatcher { - - /** - * Returns the lock expressions in the {@code @LockMethod}/{@code @UnlockMethod} annotation, if - * any. - */ - protected abstract ImmutableList getLockExpressions(MethodTree tree); - - /** Searches the method body for locks that are acquired/released. */ - protected abstract Set getActual(MethodTree tree, VisitorState state); - - /** - * Searches the method body for the incorrect lock operation (e.g. releasing a lock in - * {@code @LockMethod}, or acquiring a lock in {@code @UnlockMethod}). - */ - protected abstract Set getUnwanted(MethodTree tree, VisitorState state); - - /** Builds the error message, given the list of locks that were not handled. */ - protected abstract String buildMessage(String unhandled); - - @Override - public Description matchMethod(MethodTree tree, VisitorState state) { - - ImmutableList lockExpressions = getLockExpressions(tree); - if (lockExpressions.isEmpty()) { - return Description.NO_MATCH; - } - - Optional> expected = - parseLockExpressions(lockExpressions, tree, state); - if (!expected.isPresent()) { - return buildDescription(tree).setMessage("Could not resolve lock expression.").build(); - } - - Set unwanted = getUnwanted(tree, state); - SetView mishandled = Sets.intersection(expected.get(), unwanted); - if (!mishandled.isEmpty()) { - String message = buildMessage(formatLockString(mishandled)); - return buildDescription(tree).setMessage(message).build(); - } - - Set actual = getActual(tree, state); - SetView unhandled = Sets.difference(expected.get(), actual); - if (!unhandled.isEmpty()) { - String message = buildMessage(formatLockString(unhandled)); - return buildDescription(tree).setMessage(message).build(); - } - - return Description.NO_MATCH; - } - - private static String formatLockString(Set locks) { - ImmutableList sortedUnhandled = - FluentIterable.from(locks) - .transform(Functions.toStringFunction()) - .toSortedList(Comparator.naturalOrder()); - return Joiner.on(", ").join(sortedUnhandled); - } - - private static Optional> parseLockExpressions( - List lockExpressions, Tree tree, VisitorState state) { - ImmutableSet.Builder builder = ImmutableSet.builder(); - for (String lockExpression : lockExpressions) { - Optional guard = - GuardedByBinder.bindString( - lockExpression, GuardedBySymbolResolver.from(tree, state), GuardedByFlags.allOn()); - if (!guard.isPresent()) { - return Optional.empty(); - } - builder.add(guard.get()); - } - return Optional.of(builder.build()); - } -} diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/LockMethodChecker.java b/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/LockMethodChecker.java deleted file mode 100644 index 03a065f7aed..00000000000 --- a/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/LockMethodChecker.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * 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.threadsafety; - -import static com.google.errorprone.BugPattern.SeverityLevel.ERROR; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.errorprone.BugPattern; -import com.google.errorprone.VisitorState; -import com.google.errorprone.annotations.concurrent.LockMethod; -import com.google.errorprone.util.ASTHelpers; -import com.sun.source.tree.MethodTree; -import java.util.Set; - -/** - * @author cushon@google.com (Liam Miller-Cushon) - */ -@BugPattern( - name = "LockMethodChecker", - altNames = {"GuardedBy"}, - summary = "This method does not acquire the locks specified by its @LockMethod annotation", - severity = ERROR) -public class LockMethodChecker extends AbstractLockMethodChecker { - - @Override - protected ImmutableList getLockExpressions(MethodTree tree) { - LockMethod lockMethod = ASTHelpers.getAnnotation(tree, LockMethod.class); - return lockMethod == null - ? ImmutableList.of() - : ImmutableList.copyOf(lockMethod.value()); - } - - @Override - protected Set getActual(MethodTree tree, VisitorState state) { - return ImmutableSet.copyOf( - HeldLockAnalyzer.AcquiredLockFinder.find(tree.getBody(), state, GuardedByFlags.allOn())); - } - - @Override - protected Set getUnwanted(MethodTree tree, VisitorState state) { - return ImmutableSet.copyOf( - HeldLockAnalyzer.ReleasedLockFinder.find(tree.getBody(), state, GuardedByFlags.allOn())); - } - - @Override - protected String buildMessage(String unhandled) { - return "The following locks are specified in this method's @LockMethod annotation but are not" - + " acquired: " - + unhandled; - } -} diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/UnlockMethodChecker.java b/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/UnlockMethodChecker.java deleted file mode 100644 index da9c4475f25..00000000000 --- a/core/src/main/java/com/google/errorprone/bugpatterns/threadsafety/UnlockMethodChecker.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * 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.threadsafety; - -import static com.google.errorprone.BugPattern.SeverityLevel.ERROR; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.errorprone.BugPattern; -import com.google.errorprone.VisitorState; -import com.google.errorprone.annotations.concurrent.UnlockMethod; -import com.google.errorprone.util.ASTHelpers; -import com.sun.source.tree.MethodTree; -import java.util.Set; - -/** - * @author cushon@google.com (Liam Miller-Cushon) - */ -@BugPattern( - name = "UnlockMethod", - altNames = {"GuardedBy"}, - summary = "This method does not acquire the locks specified by its @UnlockMethod annotation", - severity = ERROR) -public class UnlockMethodChecker extends AbstractLockMethodChecker { - - @Override - protected ImmutableList getLockExpressions(MethodTree tree) { - UnlockMethod unlockMethod = ASTHelpers.getAnnotation(tree, UnlockMethod.class); - return unlockMethod == null - ? ImmutableList.of() - : ImmutableList.copyOf(unlockMethod.value()); - } - - @Override - protected Set getActual(MethodTree tree, VisitorState state) { - return ImmutableSet.copyOf( - HeldLockAnalyzer.ReleasedLockFinder.find(tree.getBody(), state, GuardedByFlags.allOn())); - } - - @Override - protected Set getUnwanted(MethodTree tree, VisitorState state) { - return ImmutableSet.copyOf( - HeldLockAnalyzer.AcquiredLockFinder.find(tree.getBody(), state, GuardedByFlags.allOn())); - } - - @Override - protected String buildMessage(String unhandled) { - return "The following locks are specified by this method's @UnlockMethod anotation but are not" - + " released: " - + unhandled; - } -} diff --git a/core/src/main/java/com/google/errorprone/scanner/BuiltInCheckerSuppliers.java b/core/src/main/java/com/google/errorprone/scanner/BuiltInCheckerSuppliers.java index 0c1b0b9501e..d35b4ddd848 100644 --- a/core/src/main/java/com/google/errorprone/scanner/BuiltInCheckerSuppliers.java +++ b/core/src/main/java/com/google/errorprone/scanner/BuiltInCheckerSuppliers.java @@ -500,11 +500,9 @@ import com.google.errorprone.bugpatterns.threadsafety.ImmutableChecker; import com.google.errorprone.bugpatterns.threadsafety.ImmutableEnumChecker; import com.google.errorprone.bugpatterns.threadsafety.ImmutableRefactoring; -import com.google.errorprone.bugpatterns.threadsafety.LockMethodChecker; import com.google.errorprone.bugpatterns.threadsafety.StaticGuardedByInstance; import com.google.errorprone.bugpatterns.threadsafety.SynchronizeOnNonFinalField; import com.google.errorprone.bugpatterns.threadsafety.ThreadPriorityCheck; -import com.google.errorprone.bugpatterns.threadsafety.UnlockMethodChecker; import com.google.errorprone.bugpatterns.time.DateChecker; import com.google.errorprone.bugpatterns.time.DurationFrom; import com.google.errorprone.bugpatterns.time.DurationGetTemporalUnit; @@ -1051,7 +1049,6 @@ public static ScannerSupplier errorChecks() { Java7ApiChecker.class, Java8ApiChecker.class, LambdaFunctionalInterface.class, - LockMethodChecker.class, LongLiteralLowerCaseSuffix.class, MemberName.class, MethodCanBeStatic.class, @@ -1101,7 +1098,6 @@ public static ScannerSupplier errorChecks() { TypeParameterNaming.class, TypeToString.class, UngroupedOverloads.class, - UnlockMethodChecker.class, UnnecessarilyFullyQualified.class, UnnecessarilyVisible.class, UnnecessaryAnonymousClass.class, diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/LockMethodCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/LockMethodCheckerTest.java deleted file mode 100644 index 6a999b85d47..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/LockMethodCheckerTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * 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.threadsafety; - -import com.google.errorprone.CompilationTestHelper; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** {@link LockMethodChecker}Test */ -@RunWith(JUnit4.class) -public class LockMethodCheckerTest { - private final CompilationTestHelper compilationHelper = - CompilationTestHelper.newInstance(LockMethodChecker.class, getClass()); - - @Test - public void testLocked() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import com.google.errorprone.annotations.concurrent.LockMethod;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " Lock lock1;", - " Lock lock2;", - " @LockMethod({\"lock1\", \"lock2\"})", - " void m() {", - " lock1.lock();", - " lock2.lock();", - " }", - "}") - .doTest(); - } - - @Test - public void testLockedAndUnlocked() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import com.google.errorprone.annotations.concurrent.LockMethod;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " Lock lock1;", - " Lock lock2;", - " // BUG: Diagnostic contains: not acquired: this.lock1, this.lock2", - " @LockMethod({\"lock1\", \"lock2\"}) void m() {", - " lock1.lock();", - " lock2.lock();", - " lock1.unlock();", - " lock2.unlock();", - " }", - "}") - .doTest(); - } - - @Test - public void testLockedRWLock() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.LockMethod;", - "import java.util.concurrent.locks.ReentrantReadWriteLock;", - "class Test {", - " ReentrantReadWriteLock lock;", - " @LockMethod(\"lock\")", - " void m() {", - " lock.readLock().lock();", - " }", - " @LockMethod(\"lock\")", - " void n() {", - " lock.writeLock().lock();", - " }", - "}") - .doTest(); - } - - @Test - public void testLockedMonitor() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.LockMethod;", - "import com.google.common.util.concurrent.Monitor;", - "class Test {", - " Monitor monitor;", - " @LockMethod(\"monitor\")", - " void m() {", - " monitor.enter();", - " }", - "}") - .doTest(); - } - - @Test - public void testNotLocked() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import com.google.errorprone.annotations.concurrent.LockMethod;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " Lock lock1;", - " Lock lock2;", - " // BUG: Diagnostic contains: not acquired: this.lock1, this.lock2", - " @LockMethod({\"lock1\", \"lock2\"}) void m() {}", - "}") - .doTest(); - } - - @Test - public void testNotLockedRWLock() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.LockMethod;", - "import java.util.concurrent.locks.ReentrantReadWriteLock;", - "class Test {", - " ReentrantReadWriteLock lock;", - " // BUG: Diagnostic contains: not acquired: this.lock", - " @LockMethod(\"lock\") void n() {}", - "}") - .doTest(); - } - - @Test - public void testNotLockedMonitor() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.LockMethod;", - "import com.google.common.util.concurrent.Monitor;", - "class Test {", - " Monitor monitor;", - " // BUG: Diagnostic contains: not acquired: this.monitor", - " @LockMethod(\"monitor\") void m() {}", - "}") - .doTest(); - } - - @Test - public void testBadLockExpression() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.LockMethod;", - "class Test {", - " // BUG: Diagnostic contains: Could not resolve lock expression.", - " @LockMethod(\"mu\") void m() {}", - "}") - .doTest(); - } -} diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/UnlockMethodCheckerTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/UnlockMethodCheckerTest.java deleted file mode 100644 index c0d7f71ae37..00000000000 --- a/core/src/test/java/com/google/errorprone/bugpatterns/threadsafety/UnlockMethodCheckerTest.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2014 The Error Prone Authors. - * - * 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.threadsafety; - -import com.google.errorprone.CompilationTestHelper; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** {@link UnlockMethodChecker}Test */ -@RunWith(JUnit4.class) -public class UnlockMethodCheckerTest { - private final CompilationTestHelper compilationHelper = - CompilationTestHelper.newInstance(UnlockMethodChecker.class, getClass()); - - @Test - public void testUnlocked() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import com.google.errorprone.annotations.concurrent.UnlockMethod;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " Lock lock1;", - " Lock lock2;", - " @UnlockMethod({\"lock1\", \"lock2\"}) void m() {", - " lock1.unlock();", - " lock2.unlock();", - " }", - "}") - .doTest(); - } - - @Test - public void testUnlockedAndLocked() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import com.google.errorprone.annotations.concurrent.UnlockMethod;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " Lock lock1;", - " Lock lock2;", - " // BUG: Diagnostic contains: not released: this.lock1, this.lock2", - " @UnlockMethod({\"lock1\", \"lock2\"}) void m() {", - " lock1.unlock();", - " lock2.unlock();", - " lock1.lock();", - " lock2.lock();", - " }", - "}") - .doTest(); - } - - @Test - public void testUnlockedRWLock() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.UnlockMethod;", - "import java.util.concurrent.locks.ReentrantReadWriteLock;", - "class Test {", - " ReentrantReadWriteLock lock;", - " @UnlockMethod(\"lock\")", - " void m() {", - " lock.readLock().unlock();", - " }", - " @UnlockMethod(\"lock\")", - " void n() {", - " lock.writeLock().unlock();", - " }", - "}") - .doTest(); - } - - @Test - public void testUnlockedMonitor() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.UnlockMethod;", - "import com.google.common.util.concurrent.Monitor;", - "class Test {", - " Monitor monitor;", - " @UnlockMethod(\"monitor\")", - " void m() {", - " monitor.leave();", - " }", - "}") - .doTest(); - } - - @Test - public void testNotUnlocked() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import javax.annotation.concurrent.GuardedBy;", - "import com.google.errorprone.annotations.concurrent.UnlockMethod;", - "import java.util.concurrent.locks.Lock;", - "class Test {", - " Lock lock1;", - " Lock lock2;", - " // BUG: Diagnostic contains: not released: this.lock1, this.lock2", - " @UnlockMethod({\"lock1\", \"lock2\"}) void m() {}", - "}") - .doTest(); - } - - @Test - public void testNotUnlockedRWLock() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.UnlockMethod;", - "import java.util.concurrent.locks.ReentrantReadWriteLock;", - "class Test {", - " ReentrantReadWriteLock lock;", - " // BUG: Diagnostic contains: not released: this.lock", - " @UnlockMethod(\"lock\") void n() {}", - "}") - .doTest(); - } - - @Test - public void testNotUnlockedMonitor() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.UnlockMethod;", - "import com.google.common.util.concurrent.Monitor;", - "class Test {", - " Monitor monitor;", - " // BUG: Diagnostic contains: not released: this.monitor", - " @UnlockMethod(\"monitor\") void m() {}", - "}") - .doTest(); - } - - @Test - public void testBadLockExpression() { - compilationHelper - .addSourceLines( - "threadsafety/Test.java", - "package threadsafety;", - "import com.google.errorprone.annotations.concurrent.UnlockMethod;", - "class Test {", - " // BUG: Diagnostic contains: Could not resolve lock expression.", - " @UnlockMethod(\"mu\") void m() {}", - "}") - .doTest(); - } -} diff --git a/docs/bugpattern/LockMethodChecker.md b/docs/bugpattern/LockMethodChecker.md deleted file mode 100644 index 93baa0aa22e..00000000000 --- a/docs/bugpattern/LockMethodChecker.md +++ /dev/null @@ -1,2 +0,0 @@ -Methods with the @LockMethod annotation are expected to acquire one or more -locks. The caller will hold the locks when the function finishes execution. diff --git a/docs/bugpattern/UnlockMethod.md b/docs/bugpattern/UnlockMethod.md deleted file mode 100644 index d523e33ccfd..00000000000 --- a/docs/bugpattern/UnlockMethod.md +++ /dev/null @@ -1,3 +0,0 @@ -Methods with the @UnlockMethod annotation are expected to release one or more -locks. The caller must hold the locks when the function is entered, and will not -hold them when it completes.