Skip to content

Fix logic to retrieve correct line insertion #200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/arduino.cc/builder/ctags/ctags_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@ var KNOWN_TAG_KINDS = map[string]bool{
}

type CTagsParser struct {
tags []*types.CTag
tags []*types.CTag
mainFile string
}

func (p *CTagsParser) Parse(ctagsOutput string) []*types.CTag {
func (p *CTagsParser) Parse(ctagsOutput string, mainFile string) []*types.CTag {
rows := strings.Split(ctagsOutput, "\n")
rows = removeEmpty(rows)

p.mainFile = mainFile

for _, row := range rows {
p.tags = append(p.tags, parseTag(row))
}
Expand Down
2 changes: 1 addition & 1 deletion src/arduino.cc/builder/ctags/ctags_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func produceTags(t *testing.T, filename string) []*types.CTag {
require.NoError(t, err)

parser := CTagsParser{}
return parser.Parse(string(bytes))
return parser.Parse(string(bytes), "")
}

func TestCTagsParserShouldListPrototypes(t *testing.T) {
Expand Down
8 changes: 5 additions & 3 deletions src/arduino.cc/builder/ctags/ctags_to_prototypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ func (p *CTagsParser) findLineWhereToInsertPrototypes() int {
} else {
return firstFunctionPointerAsArgument
}
} else if firstFunctionLine == -1 {
} else if firstFunctionLine != -1 {
return firstFunctionLine
} else if firstFunctionPointerAsArgument != -1 {
return firstFunctionPointerAsArgument
} else {
return firstFunctionLine
return 0
}
}

Expand Down Expand Up @@ -86,7 +88,7 @@ func (p *CTagsParser) collectFunctionNames() []string {

func (p *CTagsParser) firstFunctionAtLine() int {
for _, tag := range p.tags {
if !tagIsUnknown(tag) && isHandled(tag) && tag.Kind == KIND_FUNCTION {
if !tagIsUnknown(tag) && isHandled(tag) && tag.Kind == KIND_FUNCTION && tag.Filename == p.mainFile {
return tag.Line
}
}
Expand Down
43 changes: 26 additions & 17 deletions src/arduino.cc/builder/ctags/ctags_to_prototypes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,17 @@ import (
"github.com/stretchr/testify/require"
)

func producePrototypes(t *testing.T, filename string) ([]*types.Prototype, int) {
func producePrototypes(t *testing.T, filename string, mainFile string) ([]*types.Prototype, int) {
bytes, err := ioutil.ReadFile(filepath.Join("test_data", filename))
require.NoError(t, err)

parser := &CTagsParser{}
parser.Parse(string(bytes))
parser.Parse(string(bytes), mainFile)
return parser.GeneratePrototypes()
}

func TestCTagsToPrototypesShouldListPrototypes(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserShouldListPrototypes.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserShouldListPrototypes.txt", "/tmp/sketch7210316334309249705.cpp")
require.Equal(t, 5, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
require.Equal(t, "/tmp/sketch7210316334309249705.cpp", prototypes[0].File)
Expand All @@ -61,7 +61,7 @@ func TestCTagsToPrototypesShouldListPrototypes(t *testing.T) {
}

func TestCTagsToPrototypesShouldListTemplates(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserShouldListTemplates.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserShouldListTemplates.txt", "/tmp/sketch8398023134925534708.cpp")

require.Equal(t, 3, len(prototypes))
require.Equal(t, "template <typename T> T minimum (T a, T b);", prototypes[0].Prototype)
Expand All @@ -73,7 +73,7 @@ func TestCTagsToPrototypesShouldListTemplates(t *testing.T) {
}

func TestCTagsToPrototypesShouldListTemplates2(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserShouldListTemplates2.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserShouldListTemplates2.txt", "/tmp/sketch463160524247569568.cpp")

require.Equal(t, 4, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
Expand All @@ -86,15 +86,15 @@ func TestCTagsToPrototypesShouldListTemplates2(t *testing.T) {
}

func TestCTagsToPrototypesShouldDealWithClasses(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserShouldDealWithClasses.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserShouldDealWithClasses.txt", "/tmp/sketch9043227824785312266.cpp")

require.Equal(t, 0, len(prototypes))

require.Equal(t, 8, line)
}

func TestCTagsToPrototypesShouldDealWithStructs(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserShouldDealWithStructs.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserShouldDealWithStructs.txt", "/tmp/sketch8930345717354294915.cpp")

require.Equal(t, 3, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
Expand All @@ -106,7 +106,7 @@ func TestCTagsToPrototypesShouldDealWithStructs(t *testing.T) {
}

func TestCTagsToPrototypesShouldDealWithMacros(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserShouldDealWithMacros.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserShouldDealWithMacros.txt", "/tmp/sketch5976699731718729500.cpp")

require.Equal(t, 5, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
Expand All @@ -120,7 +120,7 @@ func TestCTagsToPrototypesShouldDealWithMacros(t *testing.T) {
}

func TestCTagsToPrototypesShouldDealFunctionWithDifferentSignatures(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserShouldDealFunctionWithDifferentSignatures.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserShouldDealFunctionWithDifferentSignatures.txt", "/tmp/test260613593/preproc/ctags_target.cpp")

require.Equal(t, 1, len(prototypes))
require.Equal(t, "boolean getBytes( byte addr, int amount );", prototypes[0].Prototype)
Expand All @@ -130,7 +130,7 @@ func TestCTagsToPrototypesShouldDealFunctionWithDifferentSignatures(t *testing.T
}

func TestCTagsToPrototypesClassMembersAreFilteredOut(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserClassMembersAreFilteredOut.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserClassMembersAreFilteredOut.txt", "/tmp/test834438754/preproc/ctags_target.cpp")

require.Equal(t, 2, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
Expand All @@ -141,7 +141,7 @@ func TestCTagsToPrototypesClassMembersAreFilteredOut(t *testing.T) {
}

func TestCTagsToPrototypesStructWithFunctions(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserStructWithFunctions.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserStructWithFunctions.txt", "/tmp/build7315640391316178285.tmp/preproc/ctags_target.cpp")

require.Equal(t, 2, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
Expand All @@ -152,7 +152,7 @@ func TestCTagsToPrototypesStructWithFunctions(t *testing.T) {
}

func TestCTagsToPrototypesDefaultArguments(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserDefaultArguments.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserDefaultArguments.txt", "/tmp/test179252494/preproc/ctags_target.cpp")

require.Equal(t, 3, len(prototypes))
require.Equal(t, "void test(int x = 1);", prototypes[0].Prototype)
Expand All @@ -164,7 +164,7 @@ func TestCTagsToPrototypesDefaultArguments(t *testing.T) {
}

func TestCTagsToPrototypesNamespace(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserNamespace.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserNamespace.txt", "/tmp/test030883150/preproc/ctags_target.cpp")

require.Equal(t, 2, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
Expand All @@ -175,7 +175,7 @@ func TestCTagsToPrototypesNamespace(t *testing.T) {
}

func TestCTagsToPrototypesStatic(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserStatic.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserStatic.txt", "/tmp/test542833488/preproc/ctags_target.cpp")

require.Equal(t, 3, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
Expand All @@ -188,7 +188,7 @@ func TestCTagsToPrototypesStatic(t *testing.T) {
}

func TestCTagsToPrototypesFunctionPointer(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserFunctionPointer.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserFunctionPointer.txt", "/tmp/test547238273/preproc/ctags_target.cpp")

require.Equal(t, 3, len(prototypes))
require.Equal(t, "void t1Callback();", prototypes[0].Prototype)
Expand All @@ -200,7 +200,7 @@ func TestCTagsToPrototypesFunctionPointer(t *testing.T) {
}

func TestCTagsToPrototypesFunctionPointers(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsParserFunctionPointers.txt")
prototypes, line := producePrototypes(t, "TestCTagsParserFunctionPointers.txt", "/tmp/test907446433/preproc/ctags_target.cpp")
require.Equal(t, 2, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
require.Equal(t, "/tmp/test907446433/preproc/ctags_target.cpp", prototypes[0].File)
Expand All @@ -210,10 +210,19 @@ func TestCTagsToPrototypesFunctionPointers(t *testing.T) {
}

func TestCTagsRunnerSketchWithClassFunction(t *testing.T) {
prototypes, _ := producePrototypes(t, "TestCTagsRunnerSketchWithClassFunction.txt")
prototypes, _ := producePrototypes(t, "TestCTagsRunnerSketchWithClassFunction.txt", "/home/megabug/Workspace/arduino-builder/src/arduino.cc/builder/test/sketch_class_function/sketch_class_function.ino")

require.Equal(t, 3, len(prototypes))
require.Equal(t, "void setup();", prototypes[0].Prototype)
require.Equal(t, "void loop();", prototypes[1].Prototype)
require.Equal(t, "void asdf();", prototypes[2].Prototype)
}

func TestCTagsRunnerSketchWithMultiFile(t *testing.T) {
prototypes, line := producePrototypes(t, "TestCTagsRunnerSketchWithMultifile.txt", " /tmp/apUNI8a/apUNI8a.ino")

require.Equal(t, 0, line)
require.Equal(t, "void A7105_Setup();", prototypes[0].Prototype)
require.Equal(t, "void A7105_Reset();", prototypes[1].Prototype)
require.Equal(t, "int A7105_calibrate_VCB(uint8_t channel);", prototypes[2].Prototype)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
allowed_ch /tmp/apUNI8a/a7105.ino /^const uint8_t allowed_ch[] = {0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82};$/;" kind:variable line:21
no_allowed_channels /tmp/apUNI8a/a7105.ino /^int no_allowed_channels = 12;$/;" kind:variable line:22
A7105_Setup /tmp/apUNI8a/a7105.ino /^void A7105_Setup() {$/;" kind:function line:26 signature:() returntype:void
A7105_Reset /tmp/apUNI8a/a7105.ino /^void A7105_Reset()$/;" kind:function line:43 signature:() returntype:void
A7105_calibrate_IF /tmp/apUNI8a/a7105.ino /^int A7105_calibrate_IF() {$/;"kind:function line:52 signature:() returntype:int
A7105_calibrate_VCB /tmp/apUNI8a/a7105.ino /^int A7105_calibrate_VCB(uint8_t channel) {$/;" kind:function line:87 signature:(uint8_t channel) returntype:int
A7105_SetPower /tmp/apUNI8a/a7105.ino /^void A7105_SetPower(int power)$/;" kind:function line:120 signature:(int power) returntype:void
A7105_Strobe /tmp/apUNI8a/a7105.ino /^void A7105_Strobe(enum A7105_State state);$/;" kind:prototype line:176 signature:(enum A7105_State state) returntype:void
A7105_Strobe /tmp/apUNI8a/a7105.ino /^void A7105_Strobe(enum A7105_State state)$/;" kind:function line:179 signature:(enum A7105_State state) returntype:void
A7105_WriteReg /tmp/apUNI8a/a7105.ino /^void A7105_WriteReg(uint8_t address, uint8_t data)$/;" kind:function line:190 signature:(uint8_t address, uint8_t data) returntype:void
A7105_ReadReg /tmp/apUNI8a/a7105.ino /^uint8_t A7105_ReadReg(uint8_t address)$/;" kind:function line:197 signature:(uint8_t address) returntype:uint8_t
A7105_WriteData /tmp/apUNI8a/a7105.ino /^void A7105_WriteData(uint8_t *dpbuffer, uint8_t len, uint8_t channel)$/;" kind:function line:211 signature:(uint8_t *dpbuffer, uint8_t len, uint8_t channel) returntype:void
A7105_ReadData /tmp/apUNI8a/a7105.ino /^void A7105_ReadData(uint8_t *dpbuffer, uint8_t len)$/;" kind:function line:229 signature:(uint8_t *dpbuffer, uint8_t len) returntype:void
A7105_WriteID /tmp/apUNI8a/a7105.ino /^void A7105_WriteID(unsigned long id)$/;" kind:function line:247 signature:(unsigned long id) returntype:void
A7105_ReadID /tmp/apUNI8a/a7105.ino /^void A7105_ReadID()$/;" kind:function line:258 signature:() returntype:void
k13 /tmp/apUNI8a/a7105.ino /^unsigned char k13;$/;" kind:variable line:272
make_test_packet /tmp/apUNI8a/a7105.ino /^void make_test_packet(uint8_t testpacket[]) {$/;" kind:function line:275 signature:(uint8_t testpacket[]) returntype:void
printpacket /tmp/apUNI8a/a7105.ino /^void printpacket(uint8_t packet[]) {$/;" kind:function line:295 signature:(uint8_t packet[]) returntype:void
A7105_shoutchannel /tmp/apUNI8a/a7105.ino /^void A7105_shoutchannel() {$/;" kind:function line:308 signature:() returntype:void
A7105_oneShout /tmp/apUNI8a/a7105.ino /^int A7105_oneShout() {$/;" kind:function line:337 signature:() returntype:int
A7105_oneShoutRAM /tmp/apUNI8a/a7105.ino /^int A7105_oneShoutRAM(unsigned char xState, unsigned char xType) {$/;" kind:function line:361 signature:(unsigned char xState, unsigned char xType) returntype:int
eavesdrop /tmp/apUNI8a/a7105.ino /^void eavesdrop() {$/;" kind:function line:391 signature:() returntype:void
A7105_findchannel /tmp/apUNI8a/a7105.ino /^uint8_t A7105_findchannel() {$/;" kind:function line:442 signature:() returntype:uint8_t
A7105_sniffchannel /tmp/apUNI8a/a7105.ino /^int A7105_sniffchannel() {$/;"kind:function line:464 signature:() returntype:int
A7105_sniffchannel /tmp/apUNI8a/a7105.ino /^void A7105_sniffchannel(uint8_t _channel) {$/;" kind:function line:484 signature:(uint8_t _channel) returntype:void
A7105_scanchannels /tmp/apUNI8a/a7105.ino /^void A7105_scanchannels(const uint8_t channels[]) {$/;" kind:function line:498 signature:(const uint8_t channels[]) returntype:void
Channels /tmp/apUNI8a/hubsan.ino /^volatile int16_t Channels[12];$/;" kind:variable line:6
initialize /tmp/apUNI8a/hubsan.ino /^static void initialize() {$/;" kind:function line:8 signature:() returntype:void
hubsan_init /tmp/apUNI8a/hubsan.ino /^int hubsan_init()$/;" kind:function line:22 signature:() returntype:int
update_crc /tmp/apUNI8a/hubsan.ino /^static void update_crc()$/;" kind:function line:80 signature:() returntype:void
recdState /tmp/apUNI8a/main.ino /^unsigned char recdState, recdType;$/;"kind:variable line:5
recdType /tmp/apUNI8a/main.ino /^unsigned char recdState, recdType;$/;"kind:variable line:5
retries /tmp/apUNI8a/main.ino /^unsigned char retries;$/;" kind:variable line:6
bwMap /tmp/apUNI8a/main.ino /^const unsigned char bwMap[4 \/* new cycle green yellow red blue (green) *\/] = {2, 6, 4, 1};$/;" kind:variable line:27
bwButton /tmp/apUNI8a/main.ino /^unsigned char bwButton, bwCycle;$/;" kind:variable line:28
bwCycle /tmp/apUNI8a/main.ino /^unsigned char bwButton, bwCycle;$/;" kind:variable line:28
checkBW /tmp/apUNI8a/main.ino /^void checkBW(void); \/* watch button increment bwCycle *\/$/;" kind:prototype line:29 signature:(void) returntype:void
ledState /tmp/apUNI8a/main.ino /^unsigned char ledState;$/;" kind:variable line:31
mySwitches /tmp/apUNI8a/main.ino /^unsigned char mySwitches;$/;" kind:variable line:32
BWMODE /tmp/apUNI8a/main.ino /^unsigned char BWMODE, BLINKMODE;$/;" kind:variable line:34
BLINKMODE /tmp/apUNI8a/main.ino /^unsigned char BWMODE, BLINKMODE;$/;" kind:variable line:34
lightFSM /tmp/apUNI8a/main.ino /^void lightFSM(void);$/;" kind:prototype line:36 signature:(void) returntype:void
blinkLEDs /tmp/apUNI8a/main.ino /^void blinkLEDs(void);$/;" kind:prototype line:37 signature:(void) returntype:void
touchTimer /tmp/apUNI8a/main.ino /^unsigned touchTimer, lastTouch;$/;" kind:variable line:38
lastTouch /tmp/apUNI8a/main.ino /^unsigned touchTimer, lastTouch;$/;" kind:variable line:38
lightTimer /tmp/apUNI8a/main.ino /^unsigned char lightTimer;$/;" kind:variable line:40
lamp /tmp/apUNI8a/main.ino /^unsigned int lamp;$/;" kind:variable line:45
loops /tmp/apUNI8a/main.ino /^unsigned long loops;$/;" kind:variable line:46
recFlag /tmp/apUNI8a/main.ino /^unsigned char recFlag; \/\/ have "we" asked for a packet?$/;" kind:variable line:48
needAck /tmp/apUNI8a/main.ino /^unsigned char needAck;$/;" kind:variable line:49
fsmFSM /tmp/apUNI8a/main.ino /^void fsmFSM(void);$/;" kind:prototype line:51 signature:(void) returntype:void
printFlag /tmp/apUNI8a/main.ino /^unsigned int printFlag;$/;" kind:variable line:52
fsmTimer /tmp/apUNI8a/main.ino /^unsigned long fsmTimer;$/;" kind:variable line:53
startval /tmp/apUNI8a/main.ino /^uint8_t startval, command;$/;" kind:variable line:57
command /tmp/apUNI8a/main.ino /^uint8_t startval, command;$/;" kind:variable line:57
iCnt /tmp/apUNI8a/main.ino /^int iCnt;$/;" kind:variable line:58
myMessage /tmp/apUNI8a/main.ino /^char myMessage[8];$/;" kind:variable line:60
ackMessage /tmp/apUNI8a/main.ino /^char ackMessage[8];$/;" kind:variable line:61
setup /tmp/apUNI8a/main.ino /^void setup() {$/;" kind:function line:63signature:() returntype:void
valid /tmp/apUNI8a/main.ino /^unsigned char valid;$/;" kind:variable line:114
loop /tmp/apUNI8a/main.ino /^void loop() {$/;" kind:function line:116signature:() returntype:void
listeni /tmp/apUNI8a/main.ino /^void listeni()$/;" kind:function line:165signature:() returntype:void
kickIt /tmp/apUNI8a/main.ino /^void kickIt(unsigned char xType)$/;" kind:function line:172 signature:(unsigned char xType) returntype:void
lightFSM /tmp/apUNI8a/main.ino /^void lightFSM()$/;" kind:function line:181 signature:() returntype:void
touchFSM /tmp/apUNI8a/main.ino /^void touchFSM()$/;" kind:function line:188 signature:() returntype:void
tween /tmp/apUNI8a/main.ino /^unsigned char tween[4] = {3, 5, 7, 11};$/;" kind:variable line:206
fsmFSM /tmp/apUNI8a/main.ino /^void fsmFSM()$/;" kind:function line:207signature:() returntype:void
doBW /tmp/apUNI8a/main.ino /^void doBW(void) {$/;" kind:function line:243signature:(void) returntype:void
checkBW /tmp/apUNI8a/main.ino /^void checkBW()$/;" kind:function line:249signature:() returntype:void
getSwitches /tmp/apUNI8a/main.ino /^unsigned char getSwitches()$/;" kind:function line:260 signature:() returntype:unsigned char
xxLamp /tmp/apUNI8a/main.ino /^unsigned char xxLamp;$/;" kind:variable line:292
setLEDs /tmp/apUNI8a/main.ino /^void setLEDs(unsigned char xx)$/;" kind:function line:294 signature:(unsigned char xx) returntype:void
blinks /tmp/apUNI8a/main.ino /^const unsigned char blinks[8] = {0, 1, 0, 1, 0, 0, 1, 1};$/;" kind:variable line:311
blinkLEDs /tmp/apUNI8a/main.ino /^void blinkLEDs()$/;" kind:function line:312 signature:() returntype:void
proto_state /tmp/apUNI8a/protocol.ino /^static uint8_t proto_state;$/;" kind:variable line:4
bind_time /tmp/apUNI8a/protocol.ino /^static uint32_t bind_time;$/;"kind:variable line:5
PROTOCOL_SetBindState /tmp/apUNI8a/protocol.ino /^void PROTOCOL_SetBindState(uint32_t msec)$/;" kind:function line:11 signature:(uint32_t msec) returntype:void
3 changes: 2 additions & 1 deletion src/arduino.cc/builder/ctags_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ func (s *CTagsRunner) Run(ctx *types.Context) error {
ctx.CTagsOutput = string(sourceBytes)

parser := &ctags.CTagsParser{}
ctx.CTagsOfPreprocessedSource = parser.Parse(ctx.CTagsOutput)
ctx.CTagsOfPreprocessedSource = parser.Parse(ctx.CTagsOutput, ctx.Sketch.MainFile.Name)

protos, line := parser.GeneratePrototypes()
if line != -1 {
ctx.PrototypesLineWhereToInsert = line
Expand Down