diff --git a/infer/tests/codetoanalyze/objcpp/componentkit/Test.mm b/infer/tests/codetoanalyze/objcpp/componentkit/Test.mm index 318e1d0da..cc1d64057 100644 --- a/infer/tests/codetoanalyze/objcpp/componentkit/Test.mm +++ b/infer/tests/codetoanalyze/objcpp/componentkit/Test.mm @@ -9,7 +9,86 @@ #import +// Mimic importing CKComponnet +@interface CKComponent : NSObject +@end +@implementation CKComponent +@end + +// Mimic importing CKCompositeComponnet +@interface CKCompositeComponent : CKComponent ++ (instancetype)newWithComponent:(CKComponent*)component; +@end +@implementation CKCompositeComponent ++ (instancetype)newWithComponent:(CKComponent*)component { + return nil; +} +@end + +// Mimic importing CKLabelComponent +typedef struct { NSString* string; } LabelAttributes; + +typedef struct { int thisStructIsEmpty; } ViewAttributes; + +typedef struct { int thisStructIsEmpty; } CKSize; + +@interface CKLabelComponent : CKCompositeComponent ++ (instancetype)newWithLabelAttributes:(LabelAttributes)labelAttributes + viewAttributes:(ViewAttributes)viewAttributes + size:(CKSize)size; +@end +@implementation CKLabelComponent ++ (instancetype)newWithLabelAttributes:(LabelAttributes)labelAttributes + viewAttributes:(ViewAttributes)viewAttributes + size:(CKSize)size { + return nil; +} +@end + +// Non-component class should be linted if in the same translation unit as a +// component or controllerimplementation @interface SomeClass : NSObject @end -@implementation SomeClass +@implementation SomeClass { + NSString* _foo; +} + +- (instancetype)init { + if (self = [super init]) { + NSString* foo = @"HI"; // error + _foo = foo; + } +} +@end + +@interface FooComponent : CKCompositeComponent +@end +@implementation FooComponent ++ (instancetype)newWithString:(NSString*)string { + // Built-in types + int builtin1 = 3; // error + const int builtin2 = 4; // no error + int const builtin3 = 1; // no error + + // Objc types + NSString* a = @"lol"; // error + NSString* const b = @"lol"; // no error + const NSString* c = @"lol"; // error + const NSString* const d = @"lol"; // no error + + // Typedef resolution + BOOL e = YES; // error + const BOOL f = YES; // no error + + // Pointer types + NSError* const error = nil; // no error + NSError* const* g = &error; // error + NSError* const* const h = &error; // no error + + return [super newWithComponent:[CKLabelComponent newWithLabelAttributes:{ + .string = [@[ a, b, c, d ] componentsJoinedByString:@", "], + } + viewAttributes:{} + size:{}]]; +} @end diff --git a/infer/tests/endtoend/objcpp/componentkit/MutableLocalVariableTest.java b/infer/tests/endtoend/objcpp/componentkit/MutableLocalVariableTest.java index b62d25463..70e8c3f15 100644 --- a/infer/tests/endtoend/objcpp/componentkit/MutableLocalVariableTest.java +++ b/infer/tests/endtoend/objcpp/componentkit/MutableLocalVariableTest.java @@ -8,11 +8,43 @@ */ package endtoend.objcpp.componentkit; + + import static org.hamcrest.MatcherAssert.assertThat; + import static utils.matchers.ResultContainsLineNumbers.containsLines; + import com.google.common.collect.ImmutableList; + import org.junit.BeforeClass; + import org.junit.ClassRule; import org.junit.Test; + import java.io.IOException; + import utils.DebuggableTemporaryFolder; + import utils.InferException; + import utils.InferResults; + import utils.InferRunner; public class MutableLocalVariableTest { + + public static final String FILE = + "infer/tests/codetoanalyze/objcpp/componentkit/Test.mm"; + private static ImmutableList inferCmd; + public static final String MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE = + "MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE"; + + @ClassRule + public static DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder(); + + @BeforeClass + public static void runInfer() throws InterruptedException, IOException { + inferCmd = InferRunner.createObjCPPInferCommand( + folder, + FILE); + } @Test - public void MLVsInComponentFile() { - // do nothing fro now + public void MLVsInComponentFile() + throws InterruptedException, IOException, InferException { + InferResults inferResults = InferRunner.runInferObjC(inferCmd); + assertThat( + "Results should contain " + MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE, + inferResults, + containsOnlyLines(new int[]{58, 69, 74, 76, 80, 85})); } } diff --git a/infer/tests/utils/InferResults.java b/infer/tests/utils/InferResults.java index 96a40da09..17a3d1408 100644 --- a/infer/tests/utils/InferResults.java +++ b/infer/tests/utils/InferResults.java @@ -68,6 +68,7 @@ public class InferResults { errorType.equals("DANGLING_POINTER_DEREFERENCE") || errorType.equals("IVAR_NOT_NULL_CHECKED") || errorType.equals("BAD_POINTER_COMPARISON") || + errorType.equals("MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE") || errorType.startsWith("ERADICATE")) { Integer errorLine = Integer.parseInt(items[5].trim()); String procedure = items[6];