View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  import java.util.Objects;
22  
23  import org.apache.bcel.classfile.LineNumber;
24  
25  /**
26   * This class represents a line number within a method, that is, give an instruction a line number corresponding to the
27   * source code line.
28   *
29   * @see LineNumber
30   * @see MethodGen
31   */
32  public class LineNumberGen implements InstructionTargeter, Cloneable {
33  
34      static final LineNumberGen[] EMPTY_ARRAY = {};
35  
36      private InstructionHandle ih;
37      private int srcLine;
38  
39      /**
40       * Create a line number.
41       *
42       * @param ih instruction handle to reference.
43       * @param srcLine source line number.
44       */
45      public LineNumberGen(final InstructionHandle ih, final int srcLine) {
46          setInstruction(ih);
47          setSourceLine(srcLine);
48      }
49  
50      @Override
51      public Object clone() {
52          try {
53              return super.clone();
54          } catch (final CloneNotSupportedException e) {
55              throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
56          }
57      }
58  
59      /**
60       * @return true, if ih is target of this line number.
61       */
62      @Override
63      public boolean containsTarget(final InstructionHandle ih) {
64          return this.ih == ih;
65      }
66  
67      /**
68       * Gets the instruction handle.
69       *
70       * @return The instruction handle.
71       */
72      public InstructionHandle getInstruction() {
73          return ih;
74      }
75  
76      /**
77       * Gets LineNumber attribute.
78       *
79       * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
80       * has been called for the instruction list.
81       *
82       * @return The line number attribute.
83       */
84      public LineNumber getLineNumber() {
85          return new LineNumber(ih.getPosition(), srcLine);
86      }
87  
88      /**
89       * Gets the source line number.
90       *
91       * @return The source line number.
92       */
93      public int getSourceLine() {
94          return srcLine;
95      }
96  
97      /**
98       * Sets the instruction handle.
99       *
100      * @param instructionHandle The instruction handle to set.
101      */
102     public void setInstruction(final InstructionHandle instructionHandle) { // TODO could be package-protected?
103         Objects.requireNonNull(instructionHandle, "instructionHandle");
104         BranchInstruction.notifyTarget(this.ih, instructionHandle, this);
105         this.ih = instructionHandle;
106     }
107 
108     /**
109      * Sets the source line number.
110      *
111      * @param srcLine The source line number to set.
112      */
113     public void setSourceLine(final int srcLine) { // TODO could be package-protected?
114         this.srcLine = srcLine;
115     }
116 
117     /**
118      * @param oldIh old target.
119      * @param newIh new target.
120      */
121     @Override
122     public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) {
123         if (oldIh != ih) {
124             throw new ClassGenException("Not targeting " + oldIh + ", but " + ih + "}");
125         }
126         setInstruction(newIh);
127     }
128 }