private bool TestIsConflictingIdentifier(string testIdentifier, string inputCode, string targetFieldName)
        {
            var vbe = MockVbeBuilder.BuildFromModules((MockVbeBuilder.TestModuleName, inputCode, ComponentType.ClassModule));

            var state = MockParser.CreateAndParse(vbe.Object);

            using (state)
            {
                var field = state.DeclarationFinder.UserDeclarations(DeclarationType.Variable)
                            .Single(d => d.IdentifierName == targetFieldName);

                var fieldModel = new FieldEncapsulationModel(field as VariableDeclaration);

                var modelFactory = EncapsulateFieldTestSupport.GetResolver(state).Resolve <IEncapsulateFieldUseBackingFieldModelFactory>();
                var model        = modelFactory.Create(new List <FieldEncapsulationModel>()
                {
                    fieldModel
                });

                var efCandidate = model.EncapsulationCandidates.First(c => c.Declaration == field);
                efCandidate.EncapsulateFlag = true;

                return(model.ConflictFinder.IsConflictingIdentifier(efCandidate, testIdentifier, out _));
            }
        }
        public void EncapsulatePublicFields_ExistingUDT()
        {
            var inputCode =
                $@"
Option Explicit

Private Type TestType
    FirstValue As Long
    SecondValue As String
End Type

Private this As TestType

Public thirdValue As Integer

Public bazz As String";

            EncapsulateFieldUseBackingUDTMemberModel modelBuilder(RubberduckParserState state, EncapsulateFieldTestsResolver resolver)
            {
                var thirdValueField           = state.DeclarationFinder.MatchName("thirdValue").Single(d => d.DeclarationType.HasFlag(DeclarationType.Variable));
                var bazzField                 = state.DeclarationFinder.MatchName("bazz").Single();
                var fieldModelThirdValueField = new FieldEncapsulationModel(thirdValueField as VariableDeclaration);
                var fieldModelBazzField       = new FieldEncapsulationModel(bazzField as VariableDeclaration);

                var inputList = new List <FieldEncapsulationModel>()
                {
                    fieldModelThirdValueField, fieldModelBazzField
                };

                var targetUDT = state.DeclarationFinder.MatchName("this").Single(d => d.DeclarationType.HasFlag(DeclarationType.Variable));

                var modelFactory = resolver.Resolve <IEncapsulateFieldUseBackingUDTMemberModelFactory>();

                return(modelFactory.Create(inputList, targetUDT));
            }

            var refactoredCode = RefactoredCode(inputCode, modelBuilder);

            StringAssert.DoesNotContain($"T{ MockVbeBuilder.TestModuleName}", refactoredCode);

            StringAssert.Contains($" ThirdValue As Integer", refactoredCode);
            StringAssert.Contains($"Property Get ThirdValue", refactoredCode);
            StringAssert.Contains($" ThirdValue = this.ThirdValue", refactoredCode);

            StringAssert.Contains($"Property Let ThirdValue", refactoredCode);
            StringAssert.Contains($" this.ThirdValue =", refactoredCode);

            StringAssert.Contains($" Bazz As String", refactoredCode);
            StringAssert.Contains($"Property Get Bazz", refactoredCode);
            StringAssert.Contains($" Bazz = this.Bazz", refactoredCode);

            StringAssert.Contains($"Property Let Bazz", refactoredCode);
            StringAssert.Contains($" this.Bazz =", refactoredCode);
        }
        public void EncapsulatePublicFields_DifferentLevelForNestedProperties()
        {
            var inputCode =
                $@"
Option Explicit

Private Type FirstType
    FirstValue As Integer
End Type

Private Type SecondType
    SecondValue As Integer
    FirstTypeValue As FirstType
End Type

Private Type ThirdType
    ThirdValue As SecondType
End Type

Private mTest As ThirdType
";

            EncapsulateFieldUseBackingUDTMemberModel modelBuilder(RubberduckParserState state, EncapsulateFieldTestsResolver resolver)
            {
                var mTestField      = state.DeclarationFinder.UserDeclarations(DeclarationType.Variable).Single(d => d.IdentifierName.Equals("mTest"));
                var fieldModelMTest = new FieldEncapsulationModel(mTestField as VariableDeclaration, false);

                var inputList = new List <FieldEncapsulationModel>()
                {
                    fieldModelMTest
                };

                var modelFactory = resolver.Resolve <IEncapsulateFieldUseBackingUDTMemberModelFactory>();

                return(modelFactory.Create(inputList));
            }

            var refactoredCode = RefactoredCode(inputCode, modelBuilder);

            StringAssert.Contains($"T{ MockVbeBuilder.TestModuleName}", refactoredCode);

            StringAssert.Contains($" Test As ThirdType", refactoredCode);
            StringAssert.Contains($"Property Get FirstValue", refactoredCode);
            StringAssert.Contains($"Property Get SecondValue", refactoredCode);

            StringAssert.Contains($" this.Test.ThirdValue.FirstTypeValue.FirstValue =", refactoredCode);
            StringAssert.Contains($" this.Test.ThirdValue.SecondValue =", refactoredCode);
        }
        public void EncapsulatePublicFields(bool isReadOnly, string propertyIdentifier)
        {
            var target    = "fizz";
            var inputCode = $"Public {target} As Integer";

            EncapsulateFieldUseBackingUDTMemberModel modelBuilder(RubberduckParserState state, EncapsulateFieldTestsResolver resolver)
            {
                var field      = state.DeclarationFinder.MatchName(target).Single();
                var fieldModel = new FieldEncapsulationModel(field as VariableDeclaration, isReadOnly);

                var modelFactory = resolver.Resolve <IEncapsulateFieldUseBackingUDTMemberModelFactory>();

                return(modelFactory.Create(new List <FieldEncapsulationModel>()
                {
                    fieldModel
                }));
            }

            var refactoredCode = RefactoredCode(inputCode, modelBuilder);

            var resultPropertyIdentifier = target.CapitalizeFirstLetter();

            var backingFieldexpression = propertyIdentifier != null
                ? $"this.{resultPropertyIdentifier}"
                : $"this.{resultPropertyIdentifier}";

            StringAssert.Contains($"T{MockVbeBuilder.TestModuleName}", refactoredCode);
            StringAssert.Contains($"Public Property Get {resultPropertyIdentifier}()", refactoredCode);
            StringAssert.Contains($"{resultPropertyIdentifier} = {backingFieldexpression}", refactoredCode);

            if (isReadOnly)
            {
                StringAssert.DoesNotContain($"Public Property Let {resultPropertyIdentifier}(", refactoredCode);
                StringAssert.DoesNotContain($"{backingFieldexpression} = ", refactoredCode);
            }
            else
            {
                StringAssert.Contains($"Public Property Let {resultPropertyIdentifier}(", refactoredCode);
                StringAssert.Contains($"{backingFieldexpression} = ", refactoredCode);
            }
        }
        public void EncapsulatePublicFields_NestedPathForPrivateUDTField()
        {
            var inputCode =
                $@"
Option Explicit

Private Type TVehicle
    Wheels As Integer
End Type

Private mVehicle As TVehicle
";

            EncapsulateFieldUseBackingUDTMemberModel modelBuilder(RubberduckParserState state, EncapsulateFieldTestsResolver resolver)
            {
                var mVehicleField           = state.DeclarationFinder.UserDeclarations(DeclarationType.Variable).Single(d => d.IdentifierName.Equals("mVehicle"));
                var fieldModelMVehicleField = new FieldEncapsulationModel(mVehicleField as VariableDeclaration, false, "Vehicle");

                var inputList = new List <FieldEncapsulationModel>()
                {
                    fieldModelMVehicleField
                };

                var modelFactory = resolver.Resolve <IEncapsulateFieldUseBackingUDTMemberModelFactory>();

                return(modelFactory.Create(inputList));
            }

            var refactoredCode = RefactoredCode(inputCode, modelBuilder);

            StringAssert.Contains($"T{ MockVbeBuilder.TestModuleName}", refactoredCode);

            StringAssert.Contains($" Vehicle As TVehicle", refactoredCode);
            StringAssert.Contains($"Property Get Wheels", refactoredCode);
            StringAssert.Contains($" Wheels = this.Vehicle.Wheels", refactoredCode);

            StringAssert.Contains($"Property Let Wheels", refactoredCode);
            StringAssert.Contains($" this.Vehicle.Wheels =", refactoredCode);
        }
        public void InvalidObjectStateTarget_Throws(string objectStateTargetIdentifier)
        {
            var inputCode =
                $@"
Option Explicit

Public Type CannotUseThis
    FirstValue As Long
    SecondValue As String
End Type

Private Type TestType
    FirstValue As Long
    SecondValue As String
End Type

Private this As TestType

Public notAnOption As CannotUseThis

Public notAUserDefinedTypeField As String";

            EncapsulateFieldUseBackingUDTMemberModel modelBuilder(RubberduckParserState state, EncapsulateFieldTestsResolver resolver)
            {
                var invalidTarget = state.DeclarationFinder.MatchName(objectStateTargetIdentifier).Single(d => d.DeclarationType.HasFlag(DeclarationType.Variable));
                var fieldModel    = new FieldEncapsulationModel(invalidTarget as VariableDeclaration);

                var modelFactory = resolver.Resolve <IEncapsulateFieldUseBackingUDTMemberModelFactory>();

                return(modelFactory.Create(new List <FieldEncapsulationModel>()
                {
                    fieldModel
                }, invalidTarget));
            }

            Assert.Throws <ArgumentException>(() => RefactoredCode(inputCode, modelBuilder));
        }
        public void RespectsGroupRelatedPropertiesIndenterSetting(bool groupRelatedProperties)
        {
            var inputCode =
                @"
Public mTestField As Long
Public mTestField1 As Long
Public mTestField2 As Long
";

            EncapsulateFieldUseBackingFieldModel modelBuilder(RubberduckParserState state, EncapsulateFieldTestsResolver resolver)
            {
                var field      = state.AllUserDeclarations.Single(d => d.IdentifierName.Equals("mTestField"));
                var fieldModel = new FieldEncapsulationModel(field as VariableDeclaration, false);

                var modelFactory = resolver.Resolve <IEncapsulateFieldUseBackingFieldModelFactory>();
                var model        = modelFactory.Create(new List <FieldEncapsulationModel>()
                {
                    fieldModel
                });

                foreach (var candidate in model.EncapsulationCandidates)
                {
                    candidate.EncapsulateFlag = true;
                }
                return(model);
            }

            var testIndenter = new Indenter(null, () =>
            {
                var s = IndenterSettingsTests.GetMockIndenterSettings();
                s.VerticallySpaceProcedures = true;
                s.LinesBetweenProcedures    = 1;
                s.GroupRelatedProperties    = groupRelatedProperties;
                return(s);
            });

            var refactoredCode = RefactoredCode(inputCode, modelBuilder, testIndenter);

            var lines           = refactoredCode.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
            var expectedGrouped = new[]
            {
                "Public Property Get TestField() As Long",
                "TestField = mTestField",
                "End Property",
                "Public Property Let TestField(ByVal RHS As Long)",
                "mTestField = RHS",
                "End Property",
                "",
                "Public Property Get TestField1() As Long",
                "TestField1 = mTestField1",
                "End Property",
                "Public Property Let TestField1(ByVal RHS As Long)",
                "mTestField1 = RHS",
                "End Property",
                "",
                "Public Property Get TestField2() As Long",
                "TestField2 = mTestField2",
                "End Property",
                "Public Property Let TestField2(ByVal RHS As Long)",
                "mTestField2 = RHS",
                "End Property",
                "",
            };

            var expectedNotGrouped = new[]
            {
                "Public Property Get TestField() As Long",
                "TestField = mTestField",
                "End Property",
                "",
                "Public Property Let TestField(ByVal RHS As Long)",
                "mTestField = RHS",
                "End Property",
                "",
                "Public Property Get TestField1() As Long",
                "TestField1 = mTestField1",
                "End Property",
                "",
                "Public Property Let TestField1(ByVal RHS As Long)",
                "mTestField1 = RHS",
                "End Property",
                "",
                "Public Property Get TestField2() As Long",
                "TestField2 = mTestField2",
                "End Property",
                "",
                "Public Property Let TestField2(ByVal RHS As Long)",
                "mTestField2 = RHS",
                "End Property",
                "",
            };

            var idx = 0;

            IList <string> expected = groupRelatedProperties
                ? expectedGrouped.ToList()
                : expectedNotGrouped.ToList();

            var refactoredLinesOfInterest = lines.SkipWhile(rl => !rl.Contains(expected[0]));

            Assert.IsTrue(refactoredLinesOfInterest.Any());

            foreach (var line in refactoredLinesOfInterest)
            {
                if (!line.Contains("="))
                {
                    StringAssert.AreEqualIgnoringCase(expected[idx], line);
                }
                idx++;
            }
        }